aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-01-13 00:33:49 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-13 00:33:49 -0500
commitff30b3642c1f56a5ae6522b78e82be867086c637 (patch)
tree160f2dfd9d98a0d64ba9eb01574888b04905b58d /drivers/net
parent9db2f1bec36805e57a003f7bb90e003815d96de8 (diff)
parent8c5d9808e95739c9001b852464fd58fd0f583280 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c32
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig2
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c45
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h2
-rw-r--r--drivers/net/wireless/mwl8k.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c12
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c6
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c13
13 files changed, 99 insertions, 41 deletions
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index 5d1c8677f180..6a3f4da7fb48 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -97,7 +97,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
97 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 97 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
98 int ret; 98 int ret;
99 u16 val; 99 u16 val;
100 u32 cksum, offset; 100 u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX;
101 101
102 /* 102 /*
103 * Read values from EEPROM and store them in the capability structure 103 * Read values from EEPROM and store them in the capability structure
@@ -116,12 +116,38 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
116 * Validate the checksum of the EEPROM date. There are some 116 * Validate the checksum of the EEPROM date. There are some
117 * devices with invalid EEPROMs. 117 * devices with invalid EEPROMs.
118 */ 118 */
119 for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { 119 AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_UPPER, val);
120 if (val) {
121 eep_max = (val & AR5K_EEPROM_SIZE_UPPER_MASK) <<
122 AR5K_EEPROM_SIZE_ENDLOC_SHIFT;
123 AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_LOWER, val);
124 eep_max = (eep_max | val) - AR5K_EEPROM_INFO_BASE;
125
126 /*
127 * Fail safe check to prevent stupid loops due
128 * to busted EEPROMs. XXX: This value is likely too
129 * big still, waiting on a better value.
130 */
131 if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) {
132 ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: "
133 "%d (0x%04x) max expected: %d (0x%04x)\n",
134 eep_max, eep_max,
135 3 * AR5K_EEPROM_INFO_MAX,
136 3 * AR5K_EEPROM_INFO_MAX);
137 return -EIO;
138 }
139 }
140
141 for (cksum = 0, offset = 0; offset < eep_max; offset++) {
120 AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); 142 AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
121 cksum ^= val; 143 cksum ^= val;
122 } 144 }
123 if (cksum != AR5K_EEPROM_INFO_CKSUM) { 145 if (cksum != AR5K_EEPROM_INFO_CKSUM) {
124 ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); 146 ATH5K_ERR(ah->ah_sc, "Invalid EEPROM "
147 "checksum: 0x%04x eep_max: 0x%04x (%s)\n",
148 cksum, eep_max,
149 eep_max == AR5K_EEPROM_INFO_MAX ?
150 "default size" : "custom size");
125 return -EIO; 151 return -EIO;
126 } 152 }
127 153
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index 0123f3521a0b..473a483bb9c3 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -37,6 +37,14 @@
37#define AR5K_EEPROM_RFKILL_POLARITY_S 1 37#define AR5K_EEPROM_RFKILL_POLARITY_S 1
38 38
39#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ 39#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
40
41/* FLASH(EEPROM) Defines for AR531X chips */
42#define AR5K_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */
43#define AR5K_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */
44#define AR5K_EEPROM_SIZE_UPPER_MASK 0xfff0
45#define AR5K_EEPROM_SIZE_UPPER_SHIFT 4
46#define AR5K_EEPROM_SIZE_ENDLOC_SHIFT 12
47
40#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ 48#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
41#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ 49#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
42#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) 50#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 03a1106ad725..5774cea23a3b 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -25,7 +25,7 @@ config ATH9K
25 25
26config ATH9K_DEBUGFS 26config ATH9K_DEBUGFS
27 bool "Atheros ath9k debugging" 27 bool "Atheros ath9k debugging"
28 depends on ATH9K 28 depends on ATH9K && DEBUG_FS
29 ---help--- 29 ---help---
30 Say Y, if you need access to ath9k's statistics for 30 Say Y, if you need access to ath9k's statistics for
31 interrupts, rate control, etc. 31 interrupts, rate control, etc.
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index e2cef2ff5d8f..1597a42731ed 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -33,11 +33,11 @@ struct ath_node;
33 33
34/* Macro to expand scalars to 64-bit objects */ 34/* Macro to expand scalars to 64-bit objects */
35 35
36#define ito64(x) (sizeof(x) == 8) ? \ 36#define ito64(x) (sizeof(x) == 1) ? \
37 (((unsigned long long int)(x)) & (0xff)) : \ 37 (((unsigned long long int)(x)) & (0xff)) : \
38 (sizeof(x) == 16) ? \ 38 (sizeof(x) == 2) ? \
39 (((unsigned long long int)(x)) & 0xffff) : \ 39 (((unsigned long long int)(x)) & 0xffff) : \
40 ((sizeof(x) == 32) ? \ 40 ((sizeof(x) == 4) ? \
41 (((unsigned long long int)(x)) & 0xffffffff) : \ 41 (((unsigned long long int)(x)) & 0xffffffff) : \
42 (unsigned long long int)(x)) 42 (unsigned long long int)(x))
43 43
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 484c5fdf7c2a..9b4b8b5c7574 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1961,7 +1961,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
1961 struct ieee80211_tx_info *info; 1961 struct ieee80211_tx_info *info;
1962 struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; 1962 struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
1963 u32 status = le32_to_cpu(tx_resp->u.status); 1963 u32 status = le32_to_cpu(tx_resp->u.status);
1964 int tid = MAX_TID_COUNT; 1964 int uninitialized_var(tid);
1965 int sta_id; 1965 int sta_id;
1966 int freed; 1966 int freed;
1967 u8 *qc = NULL; 1967 u8 *qc = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 574d36658702..5461f105bd2d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2344,6 +2344,21 @@ static void iwl_ht_conf(struct iwl_priv *priv,
2344 IWL_DEBUG_MAC80211(priv, "leave\n"); 2344 IWL_DEBUG_MAC80211(priv, "leave\n");
2345} 2345}
2346 2346
2347static inline void iwl_set_no_assoc(struct iwl_priv *priv)
2348{
2349 priv->assoc_id = 0;
2350 iwl_led_disassociate(priv);
2351 /*
2352 * inform the ucode that there is no longer an
2353 * association and that no more packets should be
2354 * sent
2355 */
2356 priv->staging_rxon.filter_flags &=
2357 ~RXON_FILTER_ASSOC_MSK;
2358 priv->staging_rxon.assoc_id = 0;
2359 iwlcore_commit_rxon(priv);
2360}
2361
2347#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) 2362#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
2348void iwl_bss_info_changed(struct ieee80211_hw *hw, 2363void iwl_bss_info_changed(struct ieee80211_hw *hw,
2349 struct ieee80211_vif *vif, 2364 struct ieee80211_vif *vif,
@@ -2475,20 +2490,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
2475 IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; 2490 IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
2476 if (!iwl_is_rfkill(priv)) 2491 if (!iwl_is_rfkill(priv))
2477 priv->cfg->ops->lib->post_associate(priv); 2492 priv->cfg->ops->lib->post_associate(priv);
2478 } else { 2493 } else
2479 priv->assoc_id = 0; 2494 iwl_set_no_assoc(priv);
2480 iwl_led_disassociate(priv);
2481
2482 /*
2483 * inform the ucode that there is no longer an
2484 * association and that no more packets should be
2485 * send
2486 */
2487 priv->staging_rxon.filter_flags &=
2488 ~RXON_FILTER_ASSOC_MSK;
2489 priv->staging_rxon.assoc_id = 0;
2490 iwlcore_commit_rxon(priv);
2491 }
2492 } 2495 }
2493 2496
2494 if (changes && iwl_is_associated(priv) && priv->assoc_id) { 2497 if (changes && iwl_is_associated(priv) && priv->assoc_id) {
@@ -2503,12 +2506,14 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
2503 } 2506 }
2504 } 2507 }
2505 2508
2506 if ((changes & BSS_CHANGED_BEACON_ENABLED) && 2509 if (changes & BSS_CHANGED_BEACON_ENABLED) {
2507 vif->bss_conf.enable_beacon) { 2510 if (vif->bss_conf.enable_beacon) {
2508 memcpy(priv->staging_rxon.bssid_addr, 2511 memcpy(priv->staging_rxon.bssid_addr,
2509 bss_conf->bssid, ETH_ALEN); 2512 bss_conf->bssid, ETH_ALEN);
2510 memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); 2513 memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
2511 iwlcore_config_ap(priv); 2514 iwlcore_config_ap(priv);
2515 } else
2516 iwl_set_no_assoc(priv);
2512 } 2517 }
2513 2518
2514 mutex_unlock(&priv->mutex); 2519 mutex_unlock(&priv->mutex);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 165d1f6e2dd9..3822cf53e368 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -711,7 +711,7 @@ extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
711extern int iwl_queue_space(const struct iwl_queue *q); 711extern int iwl_queue_space(const struct iwl_queue *q);
712static inline int iwl_queue_used(const struct iwl_queue *q, int i) 712static inline int iwl_queue_used(const struct iwl_queue *q, int i)
713{ 713{
714 return q->write_ptr > q->read_ptr ? 714 return q->write_ptr >= q->read_ptr ?
715 (i >= q->read_ptr && i < q->write_ptr) : 715 (i >= q->read_ptr && i < q->write_ptr) :
716 !(i < q->read_ptr && i >= q->write_ptr); 716 !(i < q->read_ptr && i >= q->write_ptr);
717} 717}
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 59d49159cf2a..59f92105b0c2 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -3157,8 +3157,10 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
3157 /* Clear unsupported feature flags */ 3157 /* Clear unsupported feature flags */
3158 *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC; 3158 *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC;
3159 3159
3160 if (mwl8k_fw_lock(hw)) 3160 if (mwl8k_fw_lock(hw)) {
3161 kfree(cmd);
3161 return; 3162 return;
3163 }
3162 3164
3163 if (priv->sniffer_enabled) { 3165 if (priv->sniffer_enabled) {
3164 mwl8k_enable_sniffer(hw, 0); 3166 mwl8k_enable_sniffer(hw, 0);
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 27bf887f1453..9deae41cb784 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -340,7 +340,7 @@ static int rt2800_blink_set(struct led_classdev *led_cdev,
340 rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, *delay_off); 340 rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, *delay_off);
341 rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3); 341 rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
342 rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3); 342 rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3);
343 rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 12); 343 rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 3);
344 rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3); 344 rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3);
345 rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1); 345 rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1);
346 rt2800_register_write(led->rt2x00dev, LED_CFG, reg); 346 rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 4d841c07c970..dcfc8c25d1a7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -113,6 +113,12 @@
113 ( ((unsigned long)((__skb)->data + (__header))) & 3 ) 113 ( ((unsigned long)((__skb)->data + (__header))) & 3 )
114 114
115/* 115/*
116 * Constants for extra TX headroom for alignment purposes.
117 */
118#define RT2X00_ALIGN_SIZE 4 /* Only whole frame needs alignment */
119#define RT2X00_L2PAD_SIZE 8 /* Both header & payload need alignment */
120
121/*
116 * Standard timing and size defines. 122 * Standard timing and size defines.
117 * These values should follow the ieee80211 specifications. 123 * These values should follow the ieee80211 specifications.
118 */ 124 */
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 06c43ca39bf8..265e66dba552 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -686,7 +686,17 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
686 /* 686 /*
687 * Initialize extra TX headroom required. 687 * Initialize extra TX headroom required.
688 */ 688 */
689 rt2x00dev->hw->extra_tx_headroom = rt2x00dev->ops->extra_tx_headroom; 689 rt2x00dev->hw->extra_tx_headroom =
690 max_t(unsigned int, IEEE80211_TX_STATUS_HEADROOM,
691 rt2x00dev->ops->extra_tx_headroom);
692
693 /*
694 * Take TX headroom required for alignment into account.
695 */
696 if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
697 rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE;
698 else if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
699 rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
690 700
691 /* 701 /*
692 * Register HW. 702 * Register HW.
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 239afc7a9c0b..9915a09141ef 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -104,7 +104,7 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
104 * is also mapped to the DMA so it can be used for transfering 104 * is also mapped to the DMA so it can be used for transfering
105 * additional descriptor information to the hardware. 105 * additional descriptor information to the hardware.
106 */ 106 */
107 skb_push(skb, rt2x00dev->hw->extra_tx_headroom); 107 skb_push(skb, rt2x00dev->ops->extra_tx_headroom);
108 108
109 skbdesc->skb_dma = 109 skbdesc->skb_dma =
110 dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE); 110 dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE);
@@ -112,7 +112,7 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
112 /* 112 /*
113 * Restore data pointer to original location again. 113 * Restore data pointer to original location again.
114 */ 114 */
115 skb_pull(skb, rt2x00dev->hw->extra_tx_headroom); 115 skb_pull(skb, rt2x00dev->ops->extra_tx_headroom);
116 116
117 skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; 117 skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
118} 118}
@@ -134,7 +134,7 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
134 * by the driver, but it was actually mapped to DMA. 134 * by the driver, but it was actually mapped to DMA.
135 */ 135 */
136 dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, 136 dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma,
137 skb->len + rt2x00dev->hw->extra_tx_headroom, 137 skb->len + rt2x00dev->ops->extra_tx_headroom,
138 DMA_TO_DEVICE); 138 DMA_TO_DEVICE);
139 skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; 139 skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX;
140 } 140 }
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 8ebf5c33955d..f14deb0c8514 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -987,12 +987,13 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw,
987 changed_flags &= SUPPORTED_FIF_FLAGS; 987 changed_flags &= SUPPORTED_FIF_FLAGS;
988 *new_flags &= SUPPORTED_FIF_FLAGS; 988 *new_flags &= SUPPORTED_FIF_FLAGS;
989 989
990 /* changed_flags is always populated but this driver 990 /*
991 * doesn't support all FIF flags so its possible we don't 991 * If multicast parameter (as returned by zd_op_prepare_multicast)
992 * need to do anything */ 992 * has changed, no bit in changed_flags is set. To handle this
993 if (!changed_flags) 993 * situation, we do not return if changed_flags is 0. If we do so,
994 return; 994 * we will have some issue with IPv6 which uses multicast for link
995 995 * layer address resolution.
996 */
996 if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) 997 if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI))
997 zd_mc_add_all(&hash); 998 zd_mc_add_all(&hash);
998 999