aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ieee80211/ieee80211_tx.c86
-rw-r--r--net/ieee80211/ieee80211_wx.c89
-rw-r--r--net/mac80211/aes_ccm.c2
-rw-r--r--net/mac80211/aes_ccm.h2
-rw-r--r--net/mac80211/debugfs.c43
-rw-r--r--net/mac80211/debugfs_netdev.c2
-rw-r--r--net/mac80211/debugfs_sta.c38
-rw-r--r--net/mac80211/ieee80211_i.h15
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/key.c7
-rw-r--r--net/mac80211/main.c11
-rw-r--r--net/mac80211/mlme.c68
-rw-r--r--net/mac80211/rx.c5
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/tkip.h4
-rw-r--r--net/mac80211/wep.c2
-rw-r--r--net/mac80211/wep.h2
-rw-r--r--net/mac80211/wme.c119
-rw-r--r--net/mac80211/wpa.c8
-rw-r--r--net/sctp/associola.c3
-rw-r--r--net/sctp/proc.c141
-rw-r--r--net/sctp/protocol.c3
-rw-r--r--net/sctp/sm_sideeffect.c17
-rw-r--r--net/sctp/socket.c306
-rw-r--r--net/tipc/config.c2
-rw-r--r--net/tipc/core.c6
-rw-r--r--net/tipc/core.h124
-rw-r--r--net/tipc/dbg.c231
-rw-r--r--net/tipc/dbg.h12
-rw-r--r--net/tipc/link.c20
-rw-r--r--net/tipc/msg.c10
-rw-r--r--net/tipc/name_distr.c3
-rw-r--r--net/tipc/name_table.c7
-rw-r--r--net/tipc/port.c20
-rw-r--r--net/tipc/ref.c12
-rw-r--r--net/tipc/socket.c5
-rw-r--r--net/tipc/subscr.c1
37 files changed, 722 insertions, 709 deletions
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index d8b02603cbe5..d996547f7a62 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -542,90 +542,4 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
return 1;
}
-/* Incoming 802.11 strucure is converted to a TXB
- * a block of 802.11 fragment packets (stored as skbs) */
-int ieee80211_tx_frame(struct ieee80211_device *ieee,
- struct ieee80211_hdr *frame, int hdr_len, int total_len,
- int encrypt_mpdu)
-{
- struct ieee80211_txb *txb = NULL;
- unsigned long flags;
- struct net_device_stats *stats = &ieee->stats;
- struct sk_buff *skb_frag;
- int priority = -1;
- int fraglen = total_len;
- int headroom = ieee->tx_headroom;
- struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
-
- spin_lock_irqsave(&ieee->lock, flags);
-
- if (encrypt_mpdu && (!ieee->sec.encrypt || !crypt))
- encrypt_mpdu = 0;
-
- /* If there is no driver handler to take the TXB, dont' bother
- * creating it... */
- if (!ieee->hard_start_xmit) {
- printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
- goto success;
- }
-
- if (unlikely(total_len < 24)) {
- printk(KERN_WARNING "%s: skb too small (%d).\n",
- ieee->dev->name, total_len);
- goto success;
- }
-
- if (encrypt_mpdu) {
- frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
- fraglen += crypt->ops->extra_mpdu_prefix_len +
- crypt->ops->extra_mpdu_postfix_len;
- headroom += crypt->ops->extra_mpdu_prefix_len;
- }
-
- /* When we allocate the TXB we allocate enough space for the reserve
- * and full fragment bytes (bytes_per_frag doesn't include prefix,
- * postfix, header, FCS, etc.) */
- txb = ieee80211_alloc_txb(1, fraglen, headroom, GFP_ATOMIC);
- if (unlikely(!txb)) {
- printk(KERN_WARNING "%s: Could not allocate TXB\n",
- ieee->dev->name);
- goto failed;
- }
- txb->encrypted = 0;
- txb->payload_size = fraglen;
-
- skb_frag = txb->fragments[0];
-
- memcpy(skb_put(skb_frag, total_len), frame, total_len);
-
- if (ieee->config &
- (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
- skb_put(skb_frag, 4);
-
- /* To avoid overcomplicating things, we do the corner-case frame
- * encryption in software. The only real situation where encryption is
- * needed here is during software-based shared key authentication. */
- if (encrypt_mpdu)
- ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
-
- success:
- spin_unlock_irqrestore(&ieee->lock, flags);
-
- if (txb) {
- if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) {
- stats->tx_packets++;
- stats->tx_bytes += txb->payload_size;
- return 0;
- }
- ieee80211_txb_free(txb);
- }
- return 0;
-
- failed:
- spin_unlock_irqrestore(&ieee->lock, flags);
- stats->tx_errors++;
- return 1;
-}
-
-EXPORT_SYMBOL(ieee80211_tx_frame);
EXPORT_SYMBOL(ieee80211_txb_free);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 623489afa62c..822606b615ca 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -744,98 +744,9 @@ int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
return 0;
}
-int ieee80211_wx_set_auth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu,
- char *extra)
-{
- struct ieee80211_device *ieee = netdev_priv(dev);
- unsigned long flags;
- int err = 0;
-
- spin_lock_irqsave(&ieee->lock, flags);
-
- switch (wrqu->param.flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- case IW_AUTH_CIPHER_PAIRWISE:
- case IW_AUTH_CIPHER_GROUP:
- case IW_AUTH_KEY_MGMT:
- /*
- * Host AP driver does not use these parameters and allows
- * wpa_supplicant to control them internally.
- */
- break;
- case IW_AUTH_TKIP_COUNTERMEASURES:
- break; /* FIXME */
- case IW_AUTH_DROP_UNENCRYPTED:
- ieee->drop_unencrypted = !!wrqu->param.value;
- break;
- case IW_AUTH_80211_AUTH_ALG:
- break; /* FIXME */
- case IW_AUTH_WPA_ENABLED:
- ieee->privacy_invoked = ieee->wpa_enabled = !!wrqu->param.value;
- break;
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- ieee->ieee802_1x = !!wrqu->param.value;
- break;
- case IW_AUTH_PRIVACY_INVOKED:
- ieee->privacy_invoked = !!wrqu->param.value;
- break;
- default:
- err = -EOPNOTSUPP;
- break;
- }
- spin_unlock_irqrestore(&ieee->lock, flags);
- return err;
-}
-
-int ieee80211_wx_get_auth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu,
- char *extra)
-{
- struct ieee80211_device *ieee = netdev_priv(dev);
- unsigned long flags;
- int err = 0;
-
- spin_lock_irqsave(&ieee->lock, flags);
-
- switch (wrqu->param.flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- case IW_AUTH_CIPHER_PAIRWISE:
- case IW_AUTH_CIPHER_GROUP:
- case IW_AUTH_KEY_MGMT:
- case IW_AUTH_TKIP_COUNTERMEASURES: /* FIXME */
- case IW_AUTH_80211_AUTH_ALG: /* FIXME */
- /*
- * Host AP driver does not use these parameters and allows
- * wpa_supplicant to control them internally.
- */
- err = -EOPNOTSUPP;
- break;
- case IW_AUTH_DROP_UNENCRYPTED:
- wrqu->param.value = ieee->drop_unencrypted;
- break;
- case IW_AUTH_WPA_ENABLED:
- wrqu->param.value = ieee->wpa_enabled;
- break;
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- wrqu->param.value = ieee->ieee802_1x;
- break;
- default:
- err = -EOPNOTSUPP;
- break;
- }
- spin_unlock_irqrestore(&ieee->lock, flags);
- return err;
-}
-
EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
EXPORT_SYMBOL(ieee80211_wx_get_scan);
EXPORT_SYMBOL(ieee80211_wx_set_encode);
EXPORT_SYMBOL(ieee80211_wx_get_encode);
-
-EXPORT_SYMBOL_GPL(ieee80211_wx_set_auth);
-EXPORT_SYMBOL_GPL(ieee80211_wx_get_auth);
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 59f1691f62c8..4d4c2dfcf9a0 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -134,7 +134,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
}
-struct crypto_cipher * ieee80211_aes_key_setup_encrypt(const u8 key[])
+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
{
struct crypto_cipher *tfm;
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h
index 885f19030b29..8cd0f14aab4d 100644
--- a/net/mac80211/aes_ccm.h
+++ b/net/mac80211/aes_ccm.h
@@ -14,7 +14,7 @@
#define AES_BLOCK_LEN 16
-struct crypto_cipher * ieee80211_aes_key_setup_encrypt(const u8 key[]);
+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]);
void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
u8 *b_0, u8 *aad, u8 *data, size_t data_len,
u8 *cdata, u8 *mic);
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 1cccbfd781f6..d20d90eead1f 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -197,45 +197,6 @@ DEBUGFS_STATS_FILE(rx_handlers_fragments, 20, "%u",
DEBUGFS_STATS_FILE(tx_status_drop, 20, "%u",
local->tx_status_drop);
-static ssize_t stats_wme_rx_queue_read(struct file *file,
- char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_local *local = file->private_data;
- char buf[NUM_RX_DATA_QUEUES*15], *p = buf;
- int i;
-
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
- p += scnprintf(p, sizeof(buf)+buf-p,
- "%u\n", local->wme_rx_queue[i]);
-
- return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
-}
-
-static const struct file_operations stats_wme_rx_queue_ops = {
- .read = stats_wme_rx_queue_read,
- .open = mac80211_open_file_generic,
-};
-
-static ssize_t stats_wme_tx_queue_read(struct file *file,
- char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_local *local = file->private_data;
- char buf[NUM_TX_DATA_QUEUES*15], *p = buf;
- int i;
-
- for (i = 0; i < NUM_TX_DATA_QUEUES; i++)
- p += scnprintf(p, sizeof(buf)+buf-p,
- "%u\n", local->wme_tx_queue[i]);
-
- return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
-}
-
-static const struct file_operations stats_wme_tx_queue_ops = {
- .read = stats_wme_tx_queue_read,
- .open = mac80211_open_file_generic,
-};
#endif
DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
@@ -303,8 +264,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
DEBUGFS_STATS_ADD(rx_expand_skb_head2);
DEBUGFS_STATS_ADD(rx_handlers_fragments);
DEBUGFS_STATS_ADD(tx_status_drop);
- DEBUGFS_STATS_ADD(wme_tx_queue);
- DEBUGFS_STATS_ADD(wme_rx_queue);
#endif
DEBUGFS_STATS_ADD(dot11ACKFailureCount);
DEBUGFS_STATS_ADD(dot11RTSFailureCount);
@@ -356,8 +315,6 @@ void debugfs_hw_del(struct ieee80211_local *local)
DEBUGFS_STATS_DEL(rx_expand_skb_head2);
DEBUGFS_STATS_DEL(rx_handlers_fragments);
DEBUGFS_STATS_DEL(tx_status_drop);
- DEBUGFS_STATS_DEL(wme_tx_queue);
- DEBUGFS_STATS_DEL(wme_rx_queue);
#endif
DEBUGFS_STATS_DEL(dot11ACKFailureCount);
DEBUGFS_STATS_DEL(dot11RTSFailureCount);
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index e3326d046944..3ae5493d728b 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -528,7 +528,7 @@ void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
add_files(sdata);
}
-static int netdev_notify(struct notifier_block * nb,
+static int netdev_notify(struct notifier_block *nb,
unsigned long state,
void *ndev)
{
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 6d47a1d31b37..676a93202ff9 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -123,36 +123,6 @@ static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,
}
STA_OPS(last_seq_ctrl);
-#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
-static ssize_t sta_wme_rx_queue_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
- int i;
- struct sta_info *sta = file->private_data;
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
- p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
- sta->wme_rx_queue[i]);
- p += scnprintf(p, sizeof(buf)+buf-p, "\n");
- return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-}
-STA_OPS(wme_rx_queue);
-
-static ssize_t sta_wme_tx_queue_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- char buf[15*NUM_TX_DATA_QUEUES], *p = buf;
- int i;
- struct sta_info *sta = file->private_data;
- for (i = 0; i < NUM_TX_DATA_QUEUES; i++)
- p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
- sta->wme_tx_queue[i]);
- p += scnprintf(p, sizeof(buf)+buf-p, "\n");
- return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-}
-STA_OPS(wme_tx_queue);
-#endif
-
static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -293,10 +263,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
DEBUGFS_ADD(num_ps_buf_frames);
DEBUGFS_ADD(inactive_ms);
DEBUGFS_ADD(last_seq_ctrl);
-#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
- DEBUGFS_ADD(wme_rx_queue);
- DEBUGFS_ADD(wme_tx_queue);
-#endif
DEBUGFS_ADD(agg_status);
}
@@ -306,10 +272,6 @@ void ieee80211_sta_debugfs_remove(struct sta_info *sta)
DEBUGFS_DEL(num_ps_buf_frames);
DEBUGFS_DEL(inactive_ms);
DEBUGFS_DEL(last_seq_ctrl);
-#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
- DEBUGFS_DEL(wme_rx_queue);
- DEBUGFS_DEL(wme_tx_queue);
-#endif
DEBUGFS_DEL(agg_status);
debugfs_remove(sta->debugfs.dir);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c7314bf4bec2..d82ed20a344c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -610,8 +610,8 @@ struct ieee80211_local {
struct sta_info *sta_hash[STA_HASH_SIZE];
struct timer_list sta_cleanup;
- unsigned long state[NUM_TX_DATA_QUEUES_AMPDU];
- struct ieee80211_tx_stored_packet pending_packet[NUM_TX_DATA_QUEUES_AMPDU];
+ unsigned long state[IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_AMPDU_QUEUES];
+ struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_AMPDU_QUEUES];
struct tasklet_struct tx_pending_tasklet;
/* number of interfaces with corresponding IFF_ flags */
@@ -705,8 +705,6 @@ struct ieee80211_local {
unsigned int rx_expand_skb_head2;
unsigned int rx_handlers_fragments;
unsigned int tx_status_drop;
- unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES];
- unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
#define I802_DEBUG_INC(c) (c)++
#else /* CONFIG_MAC80211_DEBUG_COUNTERS */
#define I802_DEBUG_INC(c) do { } while (0)
@@ -764,8 +762,6 @@ struct ieee80211_local {
struct dentry *rx_expand_skb_head2;
struct dentry *rx_handlers_fragments;
struct dentry *tx_status_drop;
- struct dentry *wme_tx_queue;
- struct dentry *wme_rx_queue;
#endif
struct dentry *dot11ACKFailureCount;
struct dentry *dot11RTSFailureCount;
@@ -919,9 +915,9 @@ ieee80211_rx_result ieee80211_sta_rx_scan(
void ieee80211_rx_bss_list_init(struct net_device *dev);
void ieee80211_rx_bss_list_deinit(struct net_device *dev);
int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len);
-struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
- struct sk_buff *skb, u8 *bssid,
- u8 *addr);
+struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev,
+ struct sk_buff *skb, u8 *bssid,
+ u8 *addr);
int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason);
int ieee80211_sta_disassociate(struct net_device *dev, u16 reason);
void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
@@ -940,7 +936,6 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da,
u16 tid, u16 initiator, u16 reason);
-void sta_rx_agg_session_timer_expired(unsigned long data);
void sta_addba_resp_timer_expired(unsigned long data);
void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr);
u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 06e88a5a036d..4a8062f8b1cc 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -33,9 +33,8 @@ static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
{
int i;
- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
+ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
__skb_queue_purge(&sdata->fragments[i].skb_list);
- }
}
/* Must be called with rtnl lock held. */
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 150d66dbda9d..88b211af7c1f 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -323,6 +323,13 @@ void ieee80211_key_link(struct ieee80211_key *key,
*/
if (sta->flags & WLAN_STA_WME)
key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
+
+ /*
+ * This key is for a specific sta interface,
+ * inform the driver that it should try to store
+ * this key as pairwise key.
+ */
+ key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
} else {
if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
struct sta_info *ap;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 915afadb0602..eb347eca30b5 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -385,8 +385,8 @@ static int ieee80211_open(struct net_device *dev)
* yet be effective. Trigger execution of ieee80211_sta_work
* to fix this.
*/
- if(sdata->vif.type == IEEE80211_IF_TYPE_STA ||
- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
queue_work(local->hw.workqueue, &ifsta->work);
}
@@ -1482,7 +1482,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
return;
}
- rthdr = (struct ieee80211_tx_status_rtap_hdr*)
+ rthdr = (struct ieee80211_tx_status_rtap_hdr *)
skb_push(skb, sizeof(*rthdr));
memset(rthdr, 0, sizeof(*rthdr));
@@ -1745,6 +1745,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
goto fail_wep;
}
+ if (hw->queues > IEEE80211_MAX_QUEUES)
+ hw->queues = IEEE80211_MAX_QUEUES;
+ if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES)
+ hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES;
+
ieee80211_install_qdisc(local->mdev);
/* add one default STA interface */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 4adba09e80ca..5d7719f44bea 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -87,6 +87,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev,
u8 *ssid, size_t ssid_len);
static int ieee80211_sta_config_auth(struct net_device *dev,
struct ieee80211_if_sta *ifsta);
+static void sta_rx_agg_session_timer_expired(unsigned long data);
void ieee802_11_parse_elems(u8 *start, size_t len,
@@ -256,19 +257,8 @@ static void ieee80211_sta_def_wmm_params(struct net_device *dev,
qparam.cw_max = 1023;
qparam.txop = 0;
- for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
- local->ops->conf_tx(local_to_hw(local),
- i + IEEE80211_TX_QUEUE_DATA0,
- &qparam);
-
- if (ibss) {
- /* IBSS uses different parameters for Beacon sending */
- qparam.cw_min++;
- qparam.cw_min *= 2;
- qparam.cw_min--;
- local->ops->conf_tx(local_to_hw(local),
- IEEE80211_TX_QUEUE_BEACON, &qparam);
- }
+ for (i = 0; i < local_to_hw(local)->queues; i++)
+ local->ops->conf_tx(local_to_hw(local), i, &qparam);
}
}
@@ -305,29 +295,25 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
switch (aci) {
case 1:
- queue = IEEE80211_TX_QUEUE_DATA3;
- if (acm) {
+ queue = 3;
+ if (acm)
local->wmm_acm |= BIT(0) | BIT(3);
- }
break;
case 2:
- queue = IEEE80211_TX_QUEUE_DATA1;
- if (acm) {
+ queue = 1;
+ if (acm)
local->wmm_acm |= BIT(4) | BIT(5);
- }
break;
case 3:
- queue = IEEE80211_TX_QUEUE_DATA0;
- if (acm) {
+ queue = 0;
+ if (acm)
local->wmm_acm |= BIT(6) | BIT(7);
- }
break;
case 0:
default:
- queue = IEEE80211_TX_QUEUE_DATA2;
- if (acm) {
+ queue = 2;
+ if (acm)
local->wmm_acm |= BIT(1) | BIT(2);
- }
break;
}
@@ -727,9 +713,8 @@ static void ieee80211_send_assoc(struct net_device *dev,
if (bss) {
if (bss->capability & WLAN_CAPABILITY_PRIVACY)
capab |= WLAN_CAPABILITY_PRIVACY;
- if (bss->wmm_ie) {
+ if (bss->wmm_ie)
wmm = 1;
- }
ieee80211_rx_bss_put(dev, bss);
}
@@ -1134,8 +1119,8 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid,
struct ieee80211_mgmt *mgmt;
u16 capab;
- skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
- sizeof(mgmt->u.action.u.addba_resp));
+ skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
+
if (!skb) {
printk(KERN_DEBUG "%s: failed to allocate buffer "
"for addba resp frame\n", dev->name);
@@ -1183,9 +1168,7 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da,
struct ieee80211_mgmt *mgmt;
u16 capab;
- skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
- sizeof(mgmt->u.action.u.addba_req));
-
+ skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
if (!skb) {
printk(KERN_ERR "%s: failed to allocate buffer "
@@ -1447,8 +1430,7 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
struct ieee80211_mgmt *mgmt;
u16 params;
- skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
- sizeof(mgmt->u.action.u.delba));
+ skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
if (!skb) {
printk(KERN_ERR "%s: failed to allocate buffer "
@@ -1652,7 +1634,7 @@ timer_expired_exit:
* resetting it after each frame that arrives from the originator.
* if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
*/
-void sta_rx_agg_session_timer_expired(unsigned long data)
+static void sta_rx_agg_session_timer_expired(unsigned long data)
{
/* not an elegant detour, but there is no choice as the timer passes
* only one argument, and verious sta_info are needed here, so init
@@ -1841,9 +1823,8 @@ static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
" (reason=%d)\n",
dev->name, print_mac(mac, mgmt->sa), reason_code);
- if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) {
+ if (ifsta->flags & IEEE80211_STA_AUTHENTICATED)
printk(KERN_DEBUG "%s: deauthenticated\n", dev->name);
- }
if (ifsta->state == IEEE80211_AUTHENTICATE ||
ifsta->state == IEEE80211_ASSOCIATE ||
@@ -3553,10 +3534,12 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
bss->beacon_int = local->hw.conf.beacon_int;
bss->last_update = jiffies;
bss->capability = WLAN_CAPABILITY_IBSS;
- if (sdata->default_key) {
+
+ if (sdata->default_key)
bss->capability |= WLAN_CAPABILITY_PRIVACY;
- } else
+ else
sdata->drop_unencrypted = 0;
+
bss->supp_rates_len = sband->n_bitrates;
pos = bss->supp_rates;
for (i = 0; i < sband->n_bitrates; i++) {
@@ -4239,6 +4222,7 @@ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+
kfree(ifsta->extra_ie);
if (len == 0) {
ifsta->extra_ie = NULL;
@@ -4256,9 +4240,9 @@ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
}
-struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
- struct sk_buff *skb, u8 *bssid,
- u8 *addr)
+struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev,
+ struct sk_buff *skb, u8 *bssid,
+ u8 *addr)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 1958bfb361c6..9b5a3cbec265 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -275,11 +275,6 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
}
}
- I802_DEBUG_INC(rx->local->wme_rx_queue[tid]);
- /* only a debug counter, sta might not be assigned properly yet */
- if (rx->sta)
- I802_DEBUG_INC(rx->sta->wme_rx_queue[tid]);
-
rx->queue = tid;
/* Set skb->priority to 1d tag if highest order bit of TID is not set.
* For now, set skb->priority to 0 for other cases. */
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 7d4fe4a52929..631943e8af8b 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -257,7 +257,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
* sta_rx_agg_session_timer_expired for useage */
sta->timer_to_tid[i] = i;
/* tid to tx queue: initialize according to HW (0 is valid) */
- sta->tid_to_tx_q[i] = local->hw.queues;
+ sta->tid_to_tx_q[i] = local->hw.queues + local->hw.ampdu_queues;
/* rx */
sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE;
sta->ampdu_mlme.tid_rx[i] = NULL;
diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h
index b7c2ee763d9d..1fa0bb4dba3c 100644
--- a/net/mac80211/tkip.h
+++ b/net/mac80211/tkip.h
@@ -13,8 +13,8 @@
#include <linux/crypto.h>
#include "key.h"
-u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
- u8 iv0, u8 iv1, u8 iv2);
+u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
+ u8 iv0, u8 iv1, u8 iv2);
void ieee80211_tkip_gen_phase1key(struct ieee80211_key *key, u8 *ta,
u16 *phase1key);
void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta,
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index affcecd78c10..3cbae42ec504 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -337,7 +337,7 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
return -1;
} else {
- tx->control->key_idx = tx->key->conf.hw_key_idx;
+ tx->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))
return -1;
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h
index 363779c50658..e587172115b8 100644
--- a/net/mac80211/wep.h
+++ b/net/mac80211/wep.h
@@ -26,7 +26,7 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb,
struct ieee80211_key *key);
int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
struct ieee80211_key *key);
-u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
+u8 *ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
ieee80211_rx_result
ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx);
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index dc1598b86004..c87baf4ce979 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -19,16 +19,22 @@
#include "wme.h"
/* maximum number of hardware queues we support. */
-#define TC_80211_MAX_QUEUES 16
+#define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES)
+/* current number of hardware queues we support. */
+#define QD_NUM(hw) ((hw)->queues + (hw)->ampdu_queues)
+/*
+ * Default mapping in classifier to work with default
+ * queue setup.
+ */
const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
struct ieee80211_sched_data
{
- unsigned long qdisc_pool[BITS_TO_LONGS(TC_80211_MAX_QUEUES)];
+ unsigned long qdisc_pool[BITS_TO_LONGS(QD_MAX_QUEUES)];
struct tcf_proto *filter_list;
- struct Qdisc *queues[TC_80211_MAX_QUEUES];
- struct sk_buff_head requeued[TC_80211_MAX_QUEUES];
+ struct Qdisc *queues[QD_MAX_QUEUES];
+ struct sk_buff_head requeued[QD_MAX_QUEUES];
};
static const char llc_ip_hdr[8] = {0xAA, 0xAA, 0x3, 0, 0, 0, 0x08, 0};
@@ -95,7 +101,7 @@ static inline int wme_downgrade_ac(struct sk_buff *skb)
/* positive return value indicates which queue to use
* negative return value indicates to drop the frame */
-static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd)
+static int classify80211(struct sk_buff *skb, struct Qdisc *qd)
{
struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -106,7 +112,7 @@ static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd)
if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) {
/* management frames go on AC_VO queue, but are sent
* without QoS control fields */
- return IEEE80211_TX_QUEUE_DATA0;
+ return 0;
}
if (0 /* injected */) {
@@ -141,14 +147,15 @@ static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd)
static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
{
struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+ struct ieee80211_hw *hw = &local->hw;
struct ieee80211_sched_data *q = qdisc_priv(qd);
struct ieee80211_tx_packet_data *pkt_data =
(struct ieee80211_tx_packet_data *) skb->cb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
unsigned short fc = le16_to_cpu(hdr->frame_control);
struct Qdisc *qdisc;
- int err, queue;
struct sta_info *sta;
+ int err, queue;
u8 tid;
if (pkt_data->flags & IEEE80211_TXPD_REQUEUE) {
@@ -158,7 +165,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
if (sta) {
int ampdu_queue = sta->tid_to_tx_q[tid];
- if ((ampdu_queue < local->hw.queues) &&
+ if ((ampdu_queue < QD_NUM(hw)) &&
test_bit(ampdu_queue, q->qdisc_pool)) {
queue = ampdu_queue;
pkt_data->flags |= IEEE80211_TXPD_AMPDU;
@@ -174,6 +181,9 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
queue = classify80211(skb, qd);
+ if (unlikely(queue >= local->hw.queues))
+ queue = local->hw.queues - 1;
+
/* now we know the 1d priority, fill in the QoS header if there is one
*/
if (WLAN_FC_IS_QOS_DATA(fc)) {
@@ -193,8 +203,8 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
sta = sta_info_get(local, hdr->addr1);
if (sta) {
int ampdu_queue = sta->tid_to_tx_q[tid];
- if ((ampdu_queue < local->hw.queues) &&
- test_bit(ampdu_queue, q->qdisc_pool)) {
+ if ((ampdu_queue < QD_NUM(hw)) &&
+ test_bit(ampdu_queue, q->qdisc_pool)) {
queue = ampdu_queue;
pkt_data->flags |= IEEE80211_TXPD_AMPDU;
} else {
@@ -205,17 +215,6 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
rcu_read_unlock();
}
- if (unlikely(queue >= local->hw.queues)) {
-#if 0
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s - queue=%d (hw does not "
- "support) -> %d\n",
- __func__, queue, local->hw.queues - 1);
- }
-#endif
- queue = local->hw.queues - 1;
- }
-
if (unlikely(queue < 0)) {
kfree_skb(skb);
err = NET_XMIT_DROP;
@@ -270,7 +269,7 @@ static struct sk_buff *wme_qdiscop_dequeue(struct Qdisc* qd)
int queue;
/* check all the h/w queues in numeric/priority order */
- for (queue = 0; queue < hw->queues; queue++) {
+ for (queue = 0; queue < QD_NUM(hw); queue++) {
/* see if there is room in this hardware queue */
if ((test_bit(IEEE80211_LINK_STATE_XOFF,
&local->state[queue])) ||
@@ -308,7 +307,7 @@ static void wme_qdiscop_reset(struct Qdisc* qd)
/* QUESTION: should we have some hardware flush functionality here? */
- for (queue = 0; queue < hw->queues; queue++) {
+ for (queue = 0; queue < QD_NUM(hw); queue++) {
skb_queue_purge(&q->requeued[queue]);
qdisc_reset(q->queues[queue]);
}
@@ -326,7 +325,7 @@ static void wme_qdiscop_destroy(struct Qdisc* qd)
tcf_destroy_chain(q->filter_list);
q->filter_list = NULL;
- for (queue=0; queue < hw->queues; queue++) {
+ for (queue = 0; queue < QD_NUM(hw); queue++) {
skb_queue_purge(&q->requeued[queue]);
qdisc_destroy(q->queues[queue]);
q->queues[queue] = &noop_qdisc;
@@ -337,17 +336,6 @@ static void wme_qdiscop_destroy(struct Qdisc* qd)
/* called whenever parameters are updated on existing qdisc */
static int wme_qdiscop_tune(struct Qdisc *qd, struct nlattr *opt)
{
-/* struct ieee80211_sched_data *q = qdisc_priv(qd);
-*/
- /* check our options block is the right size */
- /* copy any options to our local structure */
-/* Ignore options block for now - always use static mapping
- struct tc_ieee80211_qopt *qopt = nla_data(opt);
-
- if (opt->nla_len < nla_attr_size(sizeof(*qopt)))
- return -EINVAL;
- memcpy(q->tag2queue, qopt->tag2queue, sizeof(qopt->tag2queue));
-*/
return 0;
}
@@ -358,7 +346,7 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt)
struct ieee80211_sched_data *q = qdisc_priv(qd);
struct net_device *dev = qd->dev;
struct ieee80211_local *local;
- int queues;
+ struct ieee80211_hw *hw;
int err = 0, i;
/* check that device is a mac80211 device */
@@ -366,29 +354,26 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt)
dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
return -EINVAL;
- /* check this device is an ieee80211 master type device */
- if (dev->type != ARPHRD_IEEE80211)
+ local = wdev_priv(dev->ieee80211_ptr);
+ hw = &local->hw;
+
+ /* only allow on master dev */
+ if (dev != local->mdev)
return -EINVAL;
- /* check that there is no qdisc currently attached to device
- * this ensures that we will be the root qdisc. (I can't find a better
- * way to test this explicitly) */
- if (dev->qdisc_sleeping != &noop_qdisc)
+ /* ensure that we are root qdisc */
+ if (qd->parent != TC_H_ROOT)
return -EINVAL;
if (qd->flags & TCQ_F_INGRESS)
return -EINVAL;
- local = wdev_priv(dev->ieee80211_ptr);
- queues = local->hw.queues;
-
/* if options were passed in, set them */
- if (opt) {
+ if (opt)
err = wme_qdiscop_tune(qd, opt);
- }
/* create child queues */
- for (i = 0; i < queues; i++) {
+ for (i = 0; i < QD_NUM(hw); i++) {
skb_queue_head_init(&q->requeued[i]);
q->queues[i] = qdisc_create_dflt(qd->dev, &pfifo_qdisc_ops,
qd->handle);
@@ -399,8 +384,8 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt)
}
}
- /* reserve all legacy QoS queues */
- for (i = 0; i < min(IEEE80211_TX_QUEUE_DATA4, queues); i++)
+ /* non-aggregation queues: reserve/mark as used */
+ for (i = 0; i < local->hw.queues; i++)
set_bit(i, q->qdisc_pool);
return err;
@@ -408,16 +393,6 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt)
static int wme_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb)
{
-/* struct ieee80211_sched_data *q = qdisc_priv(qd);
- unsigned char *p = skb->tail;
- struct tc_ieee80211_qopt opt;
-
- memcpy(&opt.tag2queue, q->tag2queue, TC_80211_MAX_TAG + 1);
- NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
-*/ return skb->len;
-/*
-nla_put_failure:
- skb_trim(skb, p - skb->data);*/
return -1;
}
@@ -430,7 +405,7 @@ static int wme_classop_graft(struct Qdisc *qd, unsigned long arg,
struct ieee80211_hw *hw = &local->hw;
unsigned long queue = arg - 1;
- if (queue >= hw->queues)
+ if (queue >= QD_NUM(hw))
return -EINVAL;
if (!new)
@@ -454,7 +429,7 @@ wme_classop_leaf(struct Qdisc *qd, unsigned long arg)
struct ieee80211_hw *hw = &local->hw;
unsigned long queue = arg - 1;
- if (queue >= hw->queues)
+ if (queue >= QD_NUM(hw))
return NULL;
return q->queues[queue];
@@ -467,7 +442,7 @@ static unsigned long wme_classop_get(struct Qdisc *qd, u32 classid)
struct ieee80211_hw *hw = &local->hw;
unsigned long queue = TC_H_MIN(classid);
- if (queue - 1 >= hw->queues)
+ if (queue - 1 >= QD_NUM(hw))
return 0;
return queue;
@@ -493,7 +468,7 @@ static int wme_classop_change(struct Qdisc *qd, u32 handle, u32 parent,
struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
struct ieee80211_hw *hw = &local->hw;
- if (cl - 1 > hw->queues)
+ if (cl - 1 > QD_NUM(hw))
return -ENOENT;
/* TODO: put code to program hardware queue parameters here,
@@ -510,7 +485,7 @@ static int wme_classop_delete(struct Qdisc *qd, unsigned long cl)
struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
struct ieee80211_hw *hw = &local->hw;
- if (cl - 1 > hw->queues)
+ if (cl - 1 > QD_NUM(hw))
return -ENOENT;
return 0;
}
@@ -523,7 +498,7 @@ static int wme_classop_dump_class(struct Qdisc *qd, unsigned long cl,
struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
struct ieee80211_hw *hw = &local->hw;
- if (cl - 1 > hw->queues)
+ if (cl - 1 > QD_NUM(hw))
return -ENOENT;
tcm->tcm_handle = TC_H_MIN(cl);
tcm->tcm_parent = qd->handle;
@@ -541,7 +516,7 @@ static void wme_classop_walk(struct Qdisc *qd, struct qdisc_walker *arg)
if (arg->stop)
return;
- for (queue = 0; queue < hw->queues; queue++) {
+ for (queue = 0; queue < QD_NUM(hw); queue++) {
if (arg->count < arg->skip) {
arg->count++;
continue;
@@ -658,10 +633,13 @@ int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
DECLARE_MAC_BUF(mac);
/* prepare the filter and save it for the SW queue
- * matching the recieved HW queue */
+ * matching the received HW queue */
+
+ if (!local->hw.ampdu_queues)
+ return -EPERM;
/* try to get a Qdisc from the pool */
- for (i = IEEE80211_TX_QUEUE_BEACON; i < local->hw.queues; i++)
+ for (i = local->hw.queues; i < QD_NUM(&local->hw); i++)
if (!test_and_set_bit(i, q->qdisc_pool)) {
ieee80211_stop_queue(local_to_hw(local), i);
sta->tid_to_tx_q[tid] = i;
@@ -690,13 +668,14 @@ void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
struct sta_info *sta, u16 tid,
u8 requeue)
{
+ struct ieee80211_hw *hw = &local->hw;
struct ieee80211_sched_data *q =
qdisc_priv(local->mdev->qdisc_sleeping);
int agg_queue = sta->tid_to_tx_q[tid];
/* return the qdisc to the pool */
clear_bit(agg_queue, q->qdisc_pool);
- sta->tid_to_tx_q[tid] = local->hw.queues;
+ sta->tid_to_tx_q[tid] = QD_NUM(hw);
if (requeue)
ieee80211_requeue(local, agg_queue);
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 45709ada8fee..42f3654e1c5e 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -228,7 +228,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx,
0x7f),
(u8) key->u.tkip.iv16);
- tx->control->key_idx = tx->key->conf.hw_key_idx;
+ tx->control->hw_key = &tx->key->conf;
return 0;
}
@@ -256,7 +256,7 @@ ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
!wpa_test) {
/* hwaccel - with no need for preallocated room for IV/ICV */
- tx->control->key_idx = tx->key->conf.hw_key_idx;
+ tx->control->hw_key = &tx->key->conf;
return TX_CONTINUE;
}
@@ -478,7 +478,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx,
if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
/* hwaccel - with preallocated room for CCMP header */
- tx->control->key_idx = key->conf.hw_key_idx;
+ tx->control->hw_key = &tx->key->conf;
return 0;
}
@@ -505,7 +505,7 @@ ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
/* hwaccel - with no need for preallocated room for CCMP "
* header or MIC fields */
- tx->control->key_idx = tx->key->conf.hw_key_idx;
+ tx->control->hw_key = &tx->key->conf;
return TX_CONTINUE;
}
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index b4cd2b71953f..7b79d1e781a8 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -136,6 +136,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
/* Set association default SACK delay */
asoc->sackdelay = msecs_to_jiffies(sp->sackdelay);
+ asoc->sackfreq = sp->sackfreq;
/* Set the association default flags controlling
* Heartbeat, SACK delay, and Path MTU Discovery.
@@ -261,6 +262,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
* already received one packet.]
*/
asoc->peer.sack_needed = 1;
+ asoc->peer.sack_cnt = 0;
/* Assume that the peer will tell us if he recognizes ASCONF
* as part of INIT exchange.
@@ -615,6 +617,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
* association configured value.
*/
peer->sackdelay = asoc->sackdelay;
+ peer->sackfreq = asoc->sackfreq;
/* Enable/disable heartbeat, SACK delay, and path MTU discovery
* based on association setting.
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 0aba759cb9b7..5dd89831eceb 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -383,3 +383,144 @@ void sctp_assocs_proc_exit(void)
{
remove_proc_entry("assocs", proc_net_sctp);
}
+
+static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos >= sctp_assoc_hashsize)
+ return NULL;
+
+ if (*pos < 0)
+ *pos = 0;
+
+ if (*pos == 0)
+ seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
+ "REM_ADDR_RTX START\n");
+
+ return (void *)pos;
+}
+
+static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ if (++*pos >= sctp_assoc_hashsize)
+ return NULL;
+
+ return pos;
+}
+
+static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v)
+{
+ return;
+}
+
+static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
+{
+ struct sctp_hashbucket *head;
+ struct sctp_ep_common *epb;
+ struct sctp_association *assoc;
+ struct hlist_node *node;
+ struct sctp_transport *tsp;
+ int hash = *(loff_t *)v;
+
+ if (hash >= sctp_assoc_hashsize)
+ return -ENOMEM;
+
+ head = &sctp_assoc_hashtable[hash];
+ sctp_local_bh_disable();
+ read_lock(&head->lock);
+ sctp_for_each_hentry(epb, node, &head->chain) {
+ assoc = sctp_assoc(epb);
+ list_for_each_entry(tsp, &assoc->peer.transport_addr_list,
+ transports) {
+ /*
+ * The remote address (ADDR)
+ */
+ tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr);
+ seq_printf(seq, " ");
+
+ /*
+ * The association ID (ASSOC_ID)
+ */
+ seq_printf(seq, "%d ", tsp->asoc->assoc_id);
+
+ /*
+ * If the Heartbeat is active (HB_ACT)
+ * Note: 1 = Active, 0 = Inactive
+ */
+ seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer));
+
+ /*
+ * Retransmit time out (RTO)
+ */
+ seq_printf(seq, "%lu ", tsp->rto);
+
+ /*
+ * Maximum path retransmit count (PATH_MAX_RTX)
+ */
+ seq_printf(seq, "%d ", tsp->pathmaxrxt);
+
+ /*
+ * remote address retransmit count (REM_ADDR_RTX)
+ * Note: We don't have a way to tally this at the moment
+ * so lets just leave it as zero for the moment
+ */
+ seq_printf(seq, "0 ");
+
+ /*
+ * remote address start time (START). This is also not
+ * currently implemented, but we can record it with a
+ * jiffies marker in a subsequent patch
+ */
+ seq_printf(seq, "0");
+
+ seq_printf(seq, "\n");
+ }
+ }
+
+ read_unlock(&head->lock);
+ sctp_local_bh_enable();
+
+ return 0;
+
+}
+
+static const struct seq_operations sctp_remaddr_ops = {
+ .start = sctp_remaddr_seq_start,
+ .next = sctp_remaddr_seq_next,
+ .stop = sctp_remaddr_seq_stop,
+ .show = sctp_remaddr_seq_show,
+};
+
+/* Cleanup the proc fs entry for 'remaddr' object. */
+void sctp_remaddr_proc_exit(void)
+{
+ remove_proc_entry("remaddr", proc_net_sctp);
+}
+
+static int sctp_remaddr_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &sctp_remaddr_ops);
+}
+
+static const struct file_operations sctp_remaddr_seq_fops = {
+ .open = sctp_remaddr_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+int __init sctp_remaddr_proc_init(void)
+{
+ struct proc_dir_entry *p;
+
+ p = create_proc_entry("remaddr", S_IRUGO, proc_net_sctp);
+ if (!p)
+ return -ENOMEM;
+ p->proc_fops = &sctp_remaddr_seq_fops;
+
+ return 0;
+}
+
+void sctp_assoc_proc_exit(void)
+{
+ remove_proc_entry("remaddr", proc_net_sctp);
+}
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 0ec234b762c2..b8bd9e014498 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -113,6 +113,8 @@ static __init int sctp_proc_init(void)
goto out_nomem;
if (sctp_assocs_proc_init())
goto out_nomem;
+ if (sctp_remaddr_proc_init())
+ goto out_nomem;
return 0;
@@ -129,6 +131,7 @@ static void sctp_proc_exit(void)
sctp_snmp_proc_exit();
sctp_eps_proc_exit();
sctp_assocs_proc_exit();
+ sctp_remaddr_proc_exit();
if (proc_net_sctp) {
proc_net_sctp = NULL;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 23a9f1a95b7d..b083312c725a 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -190,20 +190,28 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
* unacknowledged DATA chunk. ...
*/
if (!asoc->peer.sack_needed) {
- /* We will need a SACK for the next packet. */
- asoc->peer.sack_needed = 1;
+ asoc->peer.sack_cnt++;
/* Set the SACK delay timeout based on the
* SACK delay for the last transport
* data was received from, or the default
* for the association.
*/
- if (trans)
+ if (trans) {
+ /* We will need a SACK for the next packet. */
+ if (asoc->peer.sack_cnt >= trans->sackfreq - 1)
+ asoc->peer.sack_needed = 1;
+
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
trans->sackdelay;
- else
+ } else {
+ /* We will need a SACK for the next packet. */
+ if (asoc->peer.sack_cnt >= asoc->sackfreq - 1)
+ asoc->peer.sack_needed = 1;
+
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
asoc->sackdelay;
+ }
/* Restart the SACK timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
@@ -216,6 +224,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
goto nomem;
asoc->peer.sack_needed = 0;
+ asoc->peer.sack_cnt = 0;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack));
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index e7e3baf7009e..81600eea05d2 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -956,7 +956,8 @@ out:
*/
static int __sctp_connect(struct sock* sk,
struct sockaddr *kaddrs,
- int addrs_size)
+ int addrs_size,
+ sctp_assoc_t *assoc_id)
{
struct sctp_sock *sp;
struct sctp_endpoint *ep;
@@ -1111,6 +1112,8 @@ static int __sctp_connect(struct sock* sk,
timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK);
err = sctp_wait_for_connect(asoc, &timeo);
+ if (!err && assoc_id)
+ *assoc_id = asoc->assoc_id;
/* Don't free association on exit. */
asoc = NULL;
@@ -1128,7 +1131,8 @@ out_free:
/* Helper for tunneling sctp_connectx() requests through sctp_setsockopt()
*
* API 8.9
- * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt);
+ * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt,
+ * sctp_assoc_t *asoc);
*
* If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
* If the sd is an IPv6 socket, the addresses passed can either be IPv4
@@ -1144,8 +1148,10 @@ out_free:
* representation is termed a "packed array" of addresses). The caller
* specifies the number of addresses in the array with addrcnt.
*
- * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns
- * -1, and sets errno to the appropriate error code.
+ * On success, sctp_connectx() returns 0. It also sets the assoc_id to
+ * the association id of the new association. On failure, sctp_connectx()
+ * returns -1, and sets errno to the appropriate error code. The assoc_id
+ * is not touched by the kernel.
*
* For SCTP, the port given in each socket address must be the same, or
* sctp_connectx() will fail, setting errno to EINVAL.
@@ -1182,11 +1188,12 @@ out_free:
* addrs The pointer to the addresses in user land
* addrssize Size of the addrs buffer
*
- * Returns 0 if ok, <0 errno code on error.
+ * Returns >=0 if ok, <0 errno code on error.
*/
-SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
+SCTP_STATIC int __sctp_setsockopt_connectx(struct sock* sk,
struct sockaddr __user *addrs,
- int addrs_size)
+ int addrs_size,
+ sctp_assoc_t *assoc_id)
{
int err = 0;
struct sockaddr *kaddrs;
@@ -1209,13 +1216,46 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
if (__copy_from_user(kaddrs, addrs, addrs_size)) {
err = -EFAULT;
} else {
- err = __sctp_connect(sk, kaddrs, addrs_size);
+ err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id);
}
kfree(kaddrs);
+
return err;
}
+/*
+ * This is an older interface. It's kept for backward compatibility
+ * to the option that doesn't provide association id.
+ */
+SCTP_STATIC int sctp_setsockopt_connectx_old(struct sock* sk,
+ struct sockaddr __user *addrs,
+ int addrs_size)
+{
+ return __sctp_setsockopt_connectx(sk, addrs, addrs_size, NULL);
+}
+
+/*
+ * New interface for the API. The since the API is done with a socket
+ * option, to make it simple we feed back the association id is as a return
+ * indication to the call. Error is always negative and association id is
+ * always positive.
+ */
+SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
+ struct sockaddr __user *addrs,
+ int addrs_size)
+{
+ sctp_assoc_t assoc_id = 0;
+ int err = 0;
+
+ err = __sctp_setsockopt_connectx(sk, addrs, addrs_size, &assoc_id);
+
+ if (err)
+ return err;
+ else
+ return assoc_id;
+}
+
/* API 3.1.4 close() - UDP Style Syntax
* Applications use close() to perform graceful shutdown (as described in
* Section 10.1 of [SCTP]) on ALL the associations currently represented
@@ -2305,74 +2345,98 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
return 0;
}
-/* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME)
- *
- * This options will get or set the delayed ack timer. The time is set
- * in milliseconds. If the assoc_id is 0, then this sets or gets the
- * endpoints default delayed ack timer value. If the assoc_id field is
- * non-zero, then the set or get effects the specified association.
- *
- * struct sctp_assoc_value {
- * sctp_assoc_t assoc_id;
- * uint32_t assoc_value;
- * };
+/*
+ * 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK)
+ *
+ * This option will effect the way delayed acks are performed. This
+ * option allows you to get or set the delayed ack time, in
+ * milliseconds. It also allows changing the delayed ack frequency.
+ * Changing the frequency to 1 disables the delayed sack algorithm. If
+ * the assoc_id is 0, then this sets or gets the endpoints default
+ * values. If the assoc_id field is non-zero, then the set or get
+ * effects the specified association for the one to many model (the
+ * assoc_id field is ignored by the one to one model). Note that if
+ * sack_delay or sack_freq are 0 when setting this option, then the
+ * current values will remain unchanged.
+ *
+ * struct sctp_sack_info {
+ * sctp_assoc_t sack_assoc_id;
+ * uint32_t sack_delay;
+ * uint32_t sack_freq;
+ * };
*
- * assoc_id - This parameter, indicates which association the
- * user is preforming an action upon. Note that if
- * this field's value is zero then the endpoints
- * default value is changed (effecting future
- * associations only).
+ * sack_assoc_id - This parameter, indicates which association the user
+ * is performing an action upon. Note that if this field's value is
+ * zero then the endpoints default value is changed (effecting future
+ * associations only).
*
- * assoc_value - This parameter contains the number of milliseconds
- * that the user is requesting the delayed ACK timer
- * be set to. Note that this value is defined in
- * the standard to be between 200 and 500 milliseconds.
+ * sack_delay - This parameter contains the number of milliseconds that
+ * the user is requesting the delayed ACK timer be set to. Note that
+ * this value is defined in the standard to be between 200 and 500
+ * milliseconds.
*
- * Note: a value of zero will leave the value alone,
- * but disable SACK delay. A non-zero value will also
- * enable SACK delay.
+ * sack_freq - This parameter contains the number of packets that must
+ * be received before a sack is sent without waiting for the delay
+ * timer to expire. The default value for this is 2, setting this
+ * value to 1 will disable the delayed sack algorithm.
*/
-static int sctp_setsockopt_delayed_ack_time(struct sock *sk,
+static int sctp_setsockopt_delayed_ack(struct sock *sk,
char __user *optval, int optlen)
{
- struct sctp_assoc_value params;
+ struct sctp_sack_info params;
struct sctp_transport *trans = NULL;
struct sctp_association *asoc = NULL;
struct sctp_sock *sp = sctp_sk(sk);
- if (optlen != sizeof(struct sctp_assoc_value))
- return - EINVAL;
+ if (optlen == sizeof(struct sctp_sack_info)) {
+ if (copy_from_user(&params, optval, optlen))
+ return -EFAULT;
- if (copy_from_user(&params, optval, optlen))
- return -EFAULT;
+ if (params.sack_delay == 0 && params.sack_freq == 0)
+ return 0;
+ } else if (optlen == sizeof(struct sctp_assoc_value)) {
+ printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info "
+ "in delayed_ack socket option deprecated\n");
+ printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n");
+ if (copy_from_user(&params, optval, optlen))
+ return -EFAULT;
+
+ if (params.sack_delay == 0)
+ params.sack_freq = 1;
+ else
+ params.sack_freq = 0;
+ } else
+ return - EINVAL;
/* Validate value parameter. */
- if (params.assoc_value > 500)
+ if (params.sack_delay > 500)
return -EINVAL;
- /* Get association, if assoc_id != 0 and the socket is a one
+ /* Get association, if sack_assoc_id != 0 and the socket is a one
* to many style socket, and an association was not found, then
* the id was invalid.
*/
- asoc = sctp_id2assoc(sk, params.assoc_id);
- if (!asoc && params.assoc_id && sctp_style(sk, UDP))
+ asoc = sctp_id2assoc(sk, params.sack_assoc_id);
+ if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP))
return -EINVAL;
- if (params.assoc_value) {
+ if (params.sack_delay) {
if (asoc) {
asoc->sackdelay =
- msecs_to_jiffies(params.assoc_value);
+ msecs_to_jiffies(params.sack_delay);
asoc->param_flags =
(asoc->param_flags & ~SPP_SACKDELAY) |
SPP_SACKDELAY_ENABLE;
} else {
- sp->sackdelay = params.assoc_value;
+ sp->sackdelay = params.sack_delay;
sp->param_flags =
(sp->param_flags & ~SPP_SACKDELAY) |
SPP_SACKDELAY_ENABLE;
}
- } else {
+ }
+
+ if (params.sack_freq == 1) {
if (asoc) {
asoc->param_flags =
(asoc->param_flags & ~SPP_SACKDELAY) |
@@ -2382,22 +2446,40 @@ static int sctp_setsockopt_delayed_ack_time(struct sock *sk,
(sp->param_flags & ~SPP_SACKDELAY) |
SPP_SACKDELAY_DISABLE;
}
+ } else if (params.sack_freq > 1) {
+ if (asoc) {
+ asoc->sackfreq = params.sack_freq;
+ asoc->param_flags =
+ (asoc->param_flags & ~SPP_SACKDELAY) |
+ SPP_SACKDELAY_ENABLE;
+ } else {
+ sp->sackfreq = params.sack_freq;
+ sp->param_flags =
+ (sp->param_flags & ~SPP_SACKDELAY) |
+ SPP_SACKDELAY_ENABLE;
+ }
}
/* If change is for association, also apply to each transport. */
if (asoc) {
list_for_each_entry(trans, &asoc->peer.transport_addr_list,
transports) {
- if (params.assoc_value) {
+ if (params.sack_delay) {
trans->sackdelay =
- msecs_to_jiffies(params.assoc_value);
+ msecs_to_jiffies(params.sack_delay);
trans->param_flags =
(trans->param_flags & ~SPP_SACKDELAY) |
SPP_SACKDELAY_ENABLE;
- } else {
+ }
+ if (params.sack_delay == 1) {
trans->param_flags =
(trans->param_flags & ~SPP_SACKDELAY) |
SPP_SACKDELAY_DISABLE;
+ } else if (params.sack_freq > 1) {
+ trans->sackfreq = params.sack_freq;
+ trans->param_flags =
+ (trans->param_flags & ~SPP_SACKDELAY) |
+ SPP_SACKDELAY_ENABLE;
}
}
}
@@ -3164,10 +3246,18 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
optlen, SCTP_BINDX_REM_ADDR);
break;
+ case SCTP_SOCKOPT_CONNECTX_OLD:
+ /* 'optlen' is the size of the addresses buffer. */
+ retval = sctp_setsockopt_connectx_old(sk,
+ (struct sockaddr __user *)optval,
+ optlen);
+ break;
+
case SCTP_SOCKOPT_CONNECTX:
/* 'optlen' is the size of the addresses buffer. */
- retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval,
- optlen);
+ retval = sctp_setsockopt_connectx(sk,
+ (struct sockaddr __user *)optval,
+ optlen);
break;
case SCTP_DISABLE_FRAGMENTS:
@@ -3186,8 +3276,8 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen);
break;
- case SCTP_DELAYED_ACK_TIME:
- retval = sctp_setsockopt_delayed_ack_time(sk, optval, optlen);
+ case SCTP_DELAYED_ACK:
+ retval = sctp_setsockopt_delayed_ack(sk, optval, optlen);
break;
case SCTP_PARTIAL_DELIVERY_POINT:
retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen);
@@ -3294,7 +3384,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr,
/* Pass correct addr len to common routine (so it knows there
* is only one address being passed.
*/
- err = __sctp_connect(sk, addr, af->sockaddr_len);
+ err = __sctp_connect(sk, addr, af->sockaddr_len, NULL);
}
sctp_release_sock(sk);
@@ -3446,6 +3536,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
sp->pathmaxrxt = sctp_max_retrans_path;
sp->pathmtu = 0; // allow default discovery
sp->sackdelay = sctp_sack_timeout;
+ sp->sackfreq = 3;
sp->param_flags = SPP_HB_ENABLE |
SPP_PMTUD_ENABLE |
SPP_SACKDELAY_ENABLE;
@@ -3999,70 +4090,91 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
return 0;
}
-/* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME)
- *
- * This options will get or set the delayed ack timer. The time is set
- * in milliseconds. If the assoc_id is 0, then this sets or gets the
- * endpoints default delayed ack timer value. If the assoc_id field is
- * non-zero, then the set or get effects the specified association.
- *
- * struct sctp_assoc_value {
- * sctp_assoc_t assoc_id;
- * uint32_t assoc_value;
- * };
+/*
+ * 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK)
+ *
+ * This option will effect the way delayed acks are performed. This
+ * option allows you to get or set the delayed ack time, in
+ * milliseconds. It also allows changing the delayed ack frequency.
+ * Changing the frequency to 1 disables the delayed sack algorithm. If
+ * the assoc_id is 0, then this sets or gets the endpoints default
+ * values. If the assoc_id field is non-zero, then the set or get
+ * effects the specified association for the one to many model (the
+ * assoc_id field is ignored by the one to one model). Note that if
+ * sack_delay or sack_freq are 0 when setting this option, then the
+ * current values will remain unchanged.
+ *
+ * struct sctp_sack_info {
+ * sctp_assoc_t sack_assoc_id;
+ * uint32_t sack_delay;
+ * uint32_t sack_freq;
+ * };
*
- * assoc_id - This parameter, indicates which association the
- * user is preforming an action upon. Note that if
- * this field's value is zero then the endpoints
- * default value is changed (effecting future
- * associations only).
+ * sack_assoc_id - This parameter, indicates which association the user
+ * is performing an action upon. Note that if this field's value is
+ * zero then the endpoints default value is changed (effecting future
+ * associations only).
*
- * assoc_value - This parameter contains the number of milliseconds
- * that the user is requesting the delayed ACK timer
- * be set to. Note that this value is defined in
- * the standard to be between 200 and 500 milliseconds.
+ * sack_delay - This parameter contains the number of milliseconds that
+ * the user is requesting the delayed ACK timer be set to. Note that
+ * this value is defined in the standard to be between 200 and 500
+ * milliseconds.
*
- * Note: a value of zero will leave the value alone,
- * but disable SACK delay. A non-zero value will also
- * enable SACK delay.
+ * sack_freq - This parameter contains the number of packets that must
+ * be received before a sack is sent without waiting for the delay
+ * timer to expire. The default value for this is 2, setting this
+ * value to 1 will disable the delayed sack algorithm.
*/
-static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len,
+static int sctp_getsockopt_delayed_ack(struct sock *sk, int len,
char __user *optval,
int __user *optlen)
{
- struct sctp_assoc_value params;
+ struct sctp_sack_info params;
struct sctp_association *asoc = NULL;
struct sctp_sock *sp = sctp_sk(sk);
- if (len < sizeof(struct sctp_assoc_value))
- return - EINVAL;
-
- len = sizeof(struct sctp_assoc_value);
+ if (len >= sizeof(struct sctp_sack_info)) {
+ len = sizeof(struct sctp_sack_info);
- if (copy_from_user(&params, optval, len))
- return -EFAULT;
+ if (copy_from_user(&params, optval, len))
+ return -EFAULT;
+ } else if (len == sizeof(struct sctp_assoc_value)) {
+ printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info "
+ "in delayed_ack socket option deprecated\n");
+ printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n");
+ if (copy_from_user(&params, optval, len))
+ return -EFAULT;
+ } else
+ return - EINVAL;
- /* Get association, if assoc_id != 0 and the socket is a one
+ /* Get association, if sack_assoc_id != 0 and the socket is a one
* to many style socket, and an association was not found, then
* the id was invalid.
*/
- asoc = sctp_id2assoc(sk, params.assoc_id);
- if (!asoc && params.assoc_id && sctp_style(sk, UDP))
+ asoc = sctp_id2assoc(sk, params.sack_assoc_id);
+ if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP))
return -EINVAL;
if (asoc) {
/* Fetch association values. */
- if (asoc->param_flags & SPP_SACKDELAY_ENABLE)
- params.assoc_value = jiffies_to_msecs(
+ if (asoc->param_flags & SPP_SACKDELAY_ENABLE) {
+ params.sack_delay = jiffies_to_msecs(
asoc->sackdelay);
- else
- params.assoc_value = 0;
+ params.sack_freq = asoc->sackfreq;
+
+ } else {
+ params.sack_delay = 0;
+ params.sack_freq = 1;
+ }
} else {
/* Fetch socket values. */
- if (sp->param_flags & SPP_SACKDELAY_ENABLE)
- params.assoc_value = sp->sackdelay;
- else
- params.assoc_value = 0;
+ if (sp->param_flags & SPP_SACKDELAY_ENABLE) {
+ params.sack_delay = sp->sackdelay;
+ params.sack_freq = sp->sackfreq;
+ } else {
+ params.sack_delay = 0;
+ params.sack_freq = 1;
+ }
}
if (copy_to_user(optval, &params, len))
@@ -5218,8 +5330,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval = sctp_getsockopt_peer_addr_params(sk, len, optval,
optlen);
break;
- case SCTP_DELAYED_ACK_TIME:
- retval = sctp_getsockopt_delayed_ack_time(sk, len, optval,
+ case SCTP_DELAYED_ACK:
+ retval = sctp_getsockopt_delayed_ack(sk, len, optval,
optlen);
break;
case SCTP_INITMSG:
diff --git a/net/tipc/config.c b/net/tipc/config.c
index c71337a22d33..91d56f8fee9f 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -529,7 +529,7 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
break;
#endif
case TIPC_CMD_SET_LOG_SIZE:
- rep_tlv_buf = tipc_log_resize(req_tlv_area, req_tlv_space);
+ rep_tlv_buf = tipc_log_resize_cmd(req_tlv_area, req_tlv_space);
break;
case TIPC_CMD_DUMP_LOG:
rep_tlv_buf = tipc_log_dump();
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 740aac5cdfb6..6d6aa5a3c240 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -49,7 +49,7 @@
#include "config.h"
-#define TIPC_MOD_VER "1.6.3"
+#define TIPC_MOD_VER "1.6.4"
#ifndef CONFIG_TIPC_ZONES
#define CONFIG_TIPC_ZONES 3
@@ -182,7 +182,7 @@ static int __init tipc_init(void)
{
int res;
- tipc_log_reinit(CONFIG_TIPC_LOG);
+ tipc_log_resize(CONFIG_TIPC_LOG);
info("Activated (version " TIPC_MOD_VER
" compiled " __DATE__ " " __TIME__ ")\n");
@@ -209,7 +209,7 @@ static void __exit tipc_exit(void)
tipc_core_stop_net();
tipc_core_stop();
info("Deactivated\n");
- tipc_log_stop();
+ tipc_log_resize(0);
}
module_init(tipc_init);
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 5a0e4878d3b7..bd78d1705c0f 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -2,7 +2,7 @@
* net/tipc/core.h: Include file for TIPC global declarations
*
* Copyright (c) 2005-2006, Ericsson AB
- * Copyright (c) 2005-2006, Wind River Systems
+ * Copyright (c) 2005-2007, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,84 +59,108 @@
#include <linux/vmalloc.h>
/*
- * TIPC debugging code
+ * TIPC sanity test macros
*/
#define assert(i) BUG_ON(!(i))
-struct tipc_msg;
-extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG;
-extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *);
-void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*);
-void tipc_printf(struct print_buf *, const char *fmt, ...);
-void tipc_dump(struct print_buf*,const char *fmt, ...);
-
-#ifdef CONFIG_TIPC_DEBUG
-
/*
- * TIPC debug support included:
- * - system messages are printed to TIPC_OUTPUT print buffer
- * - debug messages are printed to DBG_OUTPUT print buffer
+ * TIPC system monitoring code
*/
-#define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_ERR "TIPC: " fmt, ## arg)
-#define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg)
-#define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg)
+/*
+ * TIPC's print buffer subsystem supports the following print buffers:
+ *
+ * TIPC_NULL : null buffer (i.e. print nowhere)
+ * TIPC_CONS : system console
+ * TIPC_LOG : TIPC log buffer
+ * &buf : user-defined buffer (struct print_buf *)
+ *
+ * Note: TIPC_LOG is configured to echo its output to the system console;
+ * user-defined buffers can be configured to do the same thing.
+ */
-#define dbg(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
-#define msg_dbg(msg, txt) do {if (DBG_OUTPUT != TIPC_NULL) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0)
-#define dump(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
+extern struct print_buf *const TIPC_NULL;
+extern struct print_buf *const TIPC_CONS;
+extern struct print_buf *const TIPC_LOG;
+void tipc_printf(struct print_buf *, const char *fmt, ...);
/*
- * By default, TIPC_OUTPUT is defined to be system console and TIPC log buffer,
- * while DBG_OUTPUT is the null print buffer. These defaults can be changed
- * here, or on a per .c file basis, by redefining these symbols. The following
- * print buffer options are available:
- *
- * TIPC_NULL : null buffer (i.e. print nowhere)
- * TIPC_CONS : system console
- * TIPC_LOG : TIPC log buffer
- * &buf : user-defined buffer (struct print_buf *)
- * TIPC_TEE(&buf_a,&buf_b) : list of buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG))
+ * TIPC_OUTPUT is the destination print buffer for system messages.
*/
#ifndef TIPC_OUTPUT
-#define TIPC_OUTPUT TIPC_TEE(TIPC_CONS,TIPC_LOG)
-#endif
-
-#ifndef DBG_OUTPUT
-#define DBG_OUTPUT TIPC_NULL
+#define TIPC_OUTPUT TIPC_LOG
#endif
-#else
-
/*
- * TIPC debug support not included:
- * - system messages are printed to system console
- * - debug messages are not printed
+ * TIPC can be configured to send system messages to TIPC_OUTPUT
+ * or to the system console only.
*/
+#ifdef CONFIG_TIPC_DEBUG
+
+#define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, \
+ KERN_ERR "TIPC: " fmt, ## arg)
+#define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, \
+ KERN_WARNING "TIPC: " fmt, ## arg)
+#define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, \
+ KERN_NOTICE "TIPC: " fmt, ## arg)
+
+#else
+
#define err(fmt, arg...) printk(KERN_ERR "TIPC: " fmt , ## arg)
#define info(fmt, arg...) printk(KERN_INFO "TIPC: " fmt , ## arg)
#define warn(fmt, arg...) printk(KERN_WARNING "TIPC: " fmt , ## arg)
-#define dbg(fmt, arg...) do {} while (0)
-#define msg_dbg(msg,txt) do {} while (0)
-#define dump(fmt,arg...) do {} while (0)
+#endif
+/*
+ * DBG_OUTPUT is the destination print buffer for debug messages.
+ * It defaults to the the null print buffer, but can be redefined
+ * (typically in the individual .c files being debugged) to allow
+ * selected debug messages to be generated where needed.
+ */
+
+#ifndef DBG_OUTPUT
+#define DBG_OUTPUT TIPC_NULL
+#endif
/*
- * TIPC_OUTPUT is defined to be the system console, while DBG_OUTPUT is
- * the null print buffer. Thes ensures that any system or debug messages
- * that are generated without using the above macros are handled correctly.
+ * TIPC can be configured to send debug messages to the specified print buffer
+ * (typically DBG_OUTPUT) or to suppress them entirely.
*/
-#undef TIPC_OUTPUT
-#define TIPC_OUTPUT TIPC_CONS
+#ifdef CONFIG_TIPC_DEBUG
-#undef DBG_OUTPUT
-#define DBG_OUTPUT TIPC_NULL
+#define dbg(fmt, arg...) \
+ do { \
+ if (DBG_OUTPUT != TIPC_NULL) \
+ tipc_printf(DBG_OUTPUT, fmt, ## arg); \
+ } while (0)
+#define msg_dbg(msg, txt) \
+ do { \
+ if (DBG_OUTPUT != TIPC_NULL) \
+ tipc_msg_dbg(DBG_OUTPUT, msg, txt); \
+ } while (0)
+#define dump(fmt, arg...) \
+ do { \
+ if (DBG_OUTPUT != TIPC_NULL) \
+ tipc_dump_dbg(DBG_OUTPUT, fmt, ##arg); \
+ } while (0)
+
+void tipc_msg_dbg(struct print_buf *, struct tipc_msg *, const char *);
+void tipc_dump_dbg(struct print_buf *, const char *fmt, ...);
+
+#else
+
+#define dbg(fmt, arg...) do {} while (0)
+#define msg_dbg(msg, txt) do {} while (0)
+#define dump(fmt, arg...) do {} while (0)
+
+#define tipc_msg_dbg(...) do {} while (0)
+#define tipc_dump_dbg(...) do {} while (0)
#endif
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
index e809d2a2ce06..29ecae851668 100644
--- a/net/tipc/dbg.c
+++ b/net/tipc/dbg.c
@@ -2,7 +2,7 @@
* net/tipc/dbg.c: TIPC print buffer routines for debugging
*
* Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2005-2006, Wind River Systems
+ * Copyright (c) 2005-2007, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,17 +38,43 @@
#include "config.h"
#include "dbg.h"
-static char print_string[TIPC_PB_MAX_STR];
-static DEFINE_SPINLOCK(print_lock);
+/*
+ * TIPC pre-defines the following print buffers:
+ *
+ * TIPC_NULL : null buffer (i.e. print nowhere)
+ * TIPC_CONS : system console
+ * TIPC_LOG : TIPC log buffer
+ *
+ * Additional user-defined print buffers are also permitted.
+ */
-static struct print_buf null_buf = { NULL, 0, NULL, NULL };
-struct print_buf *TIPC_NULL = &null_buf;
+static struct print_buf null_buf = { NULL, 0, NULL, 0 };
+struct print_buf *const TIPC_NULL = &null_buf;
-static struct print_buf cons_buf = { NULL, 0, NULL, NULL };
-struct print_buf *TIPC_CONS = &cons_buf;
+static struct print_buf cons_buf = { NULL, 0, NULL, 1 };
+struct print_buf *const TIPC_CONS = &cons_buf;
-static struct print_buf log_buf = { NULL, 0, NULL, NULL };
-struct print_buf *TIPC_LOG = &log_buf;
+static struct print_buf log_buf = { NULL, 0, NULL, 1 };
+struct print_buf *const TIPC_LOG = &log_buf;
+
+/*
+ * Locking policy when using print buffers.
+ *
+ * 1) tipc_printf() uses 'print_lock' to protect against concurrent access to
+ * 'print_string' when writing to a print buffer. This also protects against
+ * concurrent writes to the print buffer being written to.
+ *
+ * 2) tipc_dump() and tipc_log_XXX() leverage the aforementioned
+ * use of 'print_lock' to protect against all types of concurrent operations
+ * on their associated print buffer (not just write operations).
+ *
+ * Note: All routines of the form tipc_printbuf_XXX() are lock-free, and rely
+ * on the caller to prevent simultaneous use of the print buffer(s) being
+ * manipulated.
+ */
+
+static char print_string[TIPC_PB_MAX_STR];
+static DEFINE_SPINLOCK(print_lock);
#define FORMAT(PTR,LEN,FMT) \
@@ -60,27 +86,14 @@ struct print_buf *TIPC_LOG = &log_buf;
*(PTR + LEN) = '\0';\
}
-/*
- * Locking policy when using print buffers.
- *
- * The following routines use 'print_lock' for protection:
- * 1) tipc_printf() - to protect its print buffer(s) and 'print_string'
- * 2) TIPC_TEE() - to protect its print buffer(s)
- * 3) tipc_dump() - to protect its print buffer(s) and 'print_string'
- * 4) tipc_log_XXX() - to protect TIPC_LOG
- *
- * All routines of the form tipc_printbuf_XXX() rely on the caller to prevent
- * simultaneous use of the print buffer(s) being manipulated.
- */
-
/**
* tipc_printbuf_init - initialize print buffer to empty
* @pb: pointer to print buffer structure
* @raw: pointer to character array used by print buffer
* @size: size of character array
*
- * Makes the print buffer a null device that discards anything written to it
- * if the character array is too small (or absent).
+ * Note: If the character array is too small (or absent), the print buffer
+ * becomes a null device that discards anything written to it.
*/
void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size)
@@ -88,13 +101,13 @@ void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size)
pb->buf = raw;
pb->crs = raw;
pb->size = size;
- pb->next = NULL;
+ pb->echo = 0;
if (size < TIPC_PB_MIN_SIZE) {
pb->buf = NULL;
} else if (raw) {
pb->buf[0] = 0;
- pb->buf[size-1] = ~0;
+ pb->buf[size - 1] = ~0;
}
}
@@ -105,7 +118,11 @@ void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size)
void tipc_printbuf_reset(struct print_buf *pb)
{
- tipc_printbuf_init(pb, pb->buf, pb->size);
+ if (pb->buf) {
+ pb->crs = pb->buf;
+ pb->buf[0] = 0;
+ pb->buf[pb->size - 1] = ~0;
+ }
}
/**
@@ -141,7 +158,7 @@ int tipc_printbuf_validate(struct print_buf *pb)
if (pb->buf[pb->size - 1] == 0) {
cp_buf = kmalloc(pb->size, GFP_ATOMIC);
- if (cp_buf != NULL){
+ if (cp_buf) {
tipc_printbuf_init(&cb, cp_buf, pb->size);
tipc_printbuf_move(&cb, pb);
tipc_printbuf_move(pb, &cb);
@@ -179,15 +196,16 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
}
if (pb_to->size < pb_from->size) {
- tipc_printbuf_reset(pb_to);
- tipc_printf(pb_to, "*** PRINT BUFFER MOVE ERROR ***");
+ strcpy(pb_to->buf, "*** PRINT BUFFER MOVE ERROR ***");
+ pb_to->buf[pb_to->size - 1] = ~0;
+ pb_to->crs = strchr(pb_to->buf, 0);
return;
}
/* Copy data from char after cursor to end (if used) */
len = pb_from->buf + pb_from->size - pb_from->crs - 2;
- if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) {
+ if ((pb_from->buf[pb_from->size - 1] == 0) && (len > 0)) {
strcpy(pb_to->buf, pb_from->crs + 1);
pb_to->crs = pb_to->buf + len;
} else
@@ -203,8 +221,8 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
}
/**
- * tipc_printf - append formatted output to print buffer chain
- * @pb: pointer to chain of print buffers (may be NULL)
+ * tipc_printf - append formatted output to print buffer
+ * @pb: pointer to print buffer
* @fmt: formatted info to be printed
*/
@@ -213,68 +231,40 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
int chars_to_add;
int chars_left;
char save_char;
- struct print_buf *pb_next;
spin_lock_bh(&print_lock);
+
FORMAT(print_string, chars_to_add, fmt);
if (chars_to_add >= TIPC_PB_MAX_STR)
strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***");
- while (pb) {
- if (pb == TIPC_CONS)
- printk(print_string);
- else if (pb->buf) {
- chars_left = pb->buf + pb->size - pb->crs - 1;
- if (chars_to_add <= chars_left) {
- strcpy(pb->crs, print_string);
- pb->crs += chars_to_add;
- } else if (chars_to_add >= (pb->size - 1)) {
- strcpy(pb->buf, print_string + chars_to_add + 1
- - pb->size);
- pb->crs = pb->buf + pb->size - 1;
- } else {
- strcpy(pb->buf, print_string + chars_left);
- save_char = print_string[chars_left];
- print_string[chars_left] = 0;
- strcpy(pb->crs, print_string);
- print_string[chars_left] = save_char;
- pb->crs = pb->buf + chars_to_add - chars_left;
- }
+ if (pb->buf) {
+ chars_left = pb->buf + pb->size - pb->crs - 1;
+ if (chars_to_add <= chars_left) {
+ strcpy(pb->crs, print_string);
+ pb->crs += chars_to_add;
+ } else if (chars_to_add >= (pb->size - 1)) {
+ strcpy(pb->buf, print_string + chars_to_add + 1
+ - pb->size);
+ pb->crs = pb->buf + pb->size - 1;
+ } else {
+ strcpy(pb->buf, print_string + chars_left);
+ save_char = print_string[chars_left];
+ print_string[chars_left] = 0;
+ strcpy(pb->crs, print_string);
+ print_string[chars_left] = save_char;
+ pb->crs = pb->buf + chars_to_add - chars_left;
}
- pb_next = pb->next;
- pb->next = NULL;
- pb = pb_next;
}
- spin_unlock_bh(&print_lock);
-}
-/**
- * TIPC_TEE - perform next output operation on both print buffers
- * @b0: pointer to chain of print buffers (may be NULL)
- * @b1: pointer to print buffer to add to chain
- *
- * Returns pointer to print buffer chain.
- */
+ if (pb->echo)
+ printk(print_string);
-struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
-{
- struct print_buf *pb = b0;
-
- if (!b0 || (b0 == b1))
- return b1;
-
- spin_lock_bh(&print_lock);
- while (pb->next) {
- if ((pb->next == b1) || (pb->next == b0))
- pb->next = pb->next->next;
- else
- pb = pb->next;
- }
- pb->next = b1;
spin_unlock_bh(&print_lock);
- return b0;
}
+#ifdef CONFIG_TIPC_DEBUG
+
/**
* print_to_console - write string of bytes to console in multiple chunks
*/
@@ -321,72 +311,66 @@ static void printbuf_dump(struct print_buf *pb)
}
/**
- * tipc_dump - dump non-console print buffer(s) to console
- * @pb: pointer to chain of print buffers
+ * tipc_dump_dbg - dump (non-console) print buffer to console
+ * @pb: pointer to print buffer
*/
-void tipc_dump(struct print_buf *pb, const char *fmt, ...)
+void tipc_dump_dbg(struct print_buf *pb, const char *fmt, ...)
{
- struct print_buf *pb_next;
int len;
+ if (pb == TIPC_CONS)
+ return;
+
spin_lock_bh(&print_lock);
+
FORMAT(print_string, len, fmt);
printk(print_string);
- for (; pb; pb = pb->next) {
- if (pb != TIPC_CONS) {
- printk("\n---- Start of %s log dump ----\n\n",
- (pb == TIPC_LOG) ? "global" : "local");
- printbuf_dump(pb);
- tipc_printbuf_reset(pb);
- printk("\n---- End of dump ----\n");
- }
- pb_next = pb->next;
- pb->next = NULL;
- pb = pb_next;
- }
+ printk("\n---- Start of %s log dump ----\n\n",
+ (pb == TIPC_LOG) ? "global" : "local");
+ printbuf_dump(pb);
+ tipc_printbuf_reset(pb);
+ printk("\n---- End of dump ----\n");
+
spin_unlock_bh(&print_lock);
}
+#endif
+
/**
- * tipc_log_stop - free up TIPC log print buffer
+ * tipc_log_resize - change the size of the TIPC log buffer
+ * @log_size: print buffer size to use
*/
-void tipc_log_stop(void)
+int tipc_log_resize(int log_size)
{
+ int res = 0;
+
spin_lock_bh(&print_lock);
if (TIPC_LOG->buf) {
kfree(TIPC_LOG->buf);
TIPC_LOG->buf = NULL;
}
- spin_unlock_bh(&print_lock);
-}
-
-/**
- * tipc_log_reinit - (re)initialize TIPC log print buffer
- * @log_size: print buffer size to use
- */
-
-void tipc_log_reinit(int log_size)
-{
- tipc_log_stop();
-
if (log_size) {
if (log_size < TIPC_PB_MIN_SIZE)
log_size = TIPC_PB_MIN_SIZE;
- spin_lock_bh(&print_lock);
+ res = TIPC_LOG->echo;
tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC),
log_size);
- spin_unlock_bh(&print_lock);
+ TIPC_LOG->echo = res;
+ res = !TIPC_LOG->buf;
}
+ spin_unlock_bh(&print_lock);
+
+ return res;
}
/**
- * tipc_log_resize - reconfigure size of TIPC log buffer
+ * tipc_log_resize_cmd - reconfigure size of TIPC log buffer
*/
-struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space)
+struct sk_buff *tipc_log_resize_cmd(const void *req_tlv_area, int req_tlv_space)
{
u32 value;
@@ -397,7 +381,9 @@ struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space)
if (value != delimit(value, 0, 32768))
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
" (log size must be 0-32768)");
- tipc_log_reinit(value);
+ if (tipc_log_resize(value))
+ return tipc_cfg_reply_error_string(
+ "unable to create specified log (log size is now 0)");
return tipc_cfg_reply_none();
}
@@ -410,27 +396,32 @@ struct sk_buff *tipc_log_dump(void)
struct sk_buff *reply;
spin_lock_bh(&print_lock);
- if (!TIPC_LOG->buf)
+ if (!TIPC_LOG->buf) {
+ spin_unlock_bh(&print_lock);
reply = tipc_cfg_reply_ultra_string("log not activated\n");
- else if (tipc_printbuf_empty(TIPC_LOG))
+ } else if (tipc_printbuf_empty(TIPC_LOG)) {
+ spin_unlock_bh(&print_lock);
reply = tipc_cfg_reply_ultra_string("log is empty\n");
+ }
else {
struct tlv_desc *rep_tlv;
struct print_buf pb;
int str_len;
str_len = min(TIPC_LOG->size, 32768u);
+ spin_unlock_bh(&print_lock);
reply = tipc_cfg_reply_alloc(TLV_SPACE(str_len));
if (reply) {
rep_tlv = (struct tlv_desc *)reply->data;
tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), str_len);
+ spin_lock_bh(&print_lock);
tipc_printbuf_move(&pb, TIPC_LOG);
+ spin_unlock_bh(&print_lock);
str_len = strlen(TLV_DATA(rep_tlv)) + 1;
skb_put(reply, TLV_SPACE(str_len));
TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
}
}
- spin_unlock_bh(&print_lock);
return reply;
}
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h
index c01b085000e0..5ef1bc8f64ef 100644
--- a/net/tipc/dbg.h
+++ b/net/tipc/dbg.h
@@ -2,7 +2,7 @@
* net/tipc/dbg.h: Include file for TIPC print buffer routines
*
* Copyright (c) 1997-2006, Ericsson AB
- * Copyright (c) 2005-2006, Wind River Systems
+ * Copyright (c) 2005-2007, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,14 +42,14 @@
* @buf: pointer to character array containing print buffer contents
* @size: size of character array
* @crs: pointer to first unused space in character array (i.e. final NUL)
- * @next: used to link print buffers when printing to more than one at a time
+ * @echo: echo output to system console if non-zero
*/
struct print_buf {
char *buf;
u32 size;
char *crs;
- struct print_buf *next;
+ int echo;
};
#define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */
@@ -61,10 +61,10 @@ int tipc_printbuf_empty(struct print_buf *pb);
int tipc_printbuf_validate(struct print_buf *pb);
void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from);
-void tipc_log_reinit(int log_size);
-void tipc_log_stop(void);
+int tipc_log_resize(int log_size);
-struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space);
+struct sk_buff *tipc_log_resize_cmd(const void *req_tlv_area,
+ int req_tlv_space);
struct sk_buff *tipc_log_dump(void);
#endif
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 2a26a16e269f..bd206ebe4eea 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -147,9 +147,21 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
#define LINK_LOG_BUF_SIZE 0
-#define dbg_link(fmt, arg...) do {if (LINK_LOG_BUF_SIZE) tipc_printf(&l_ptr->print_buf, fmt, ## arg); } while(0)
-#define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) tipc_msg_print(&l_ptr->print_buf, msg, txt); } while(0)
-#define dbg_link_state(txt) do {if (LINK_LOG_BUF_SIZE) link_print(l_ptr, &l_ptr->print_buf, txt); } while(0)
+#define dbg_link(fmt, arg...) \
+ do { \
+ if (LINK_LOG_BUF_SIZE) \
+ tipc_printf(&l_ptr->print_buf, fmt, ## arg); \
+ } while (0)
+#define dbg_link_msg(msg, txt) \
+ do { \
+ if (LINK_LOG_BUF_SIZE) \
+ tipc_msg_dbg(&l_ptr->print_buf, msg, txt); \
+ } while (0)
+#define dbg_link_state(txt) \
+ do { \
+ if (LINK_LOG_BUF_SIZE) \
+ link_print(l_ptr, &l_ptr->print_buf, txt); \
+ } while (0)
#define dbg_link_dump() do { \
if (LINK_LOG_BUF_SIZE) { \
tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \
@@ -1651,7 +1663,7 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf)
struct tipc_msg *msg = buf_msg(buf);
warn("Retransmission failure on link <%s>\n", l_ptr->name);
- tipc_msg_print(TIPC_OUTPUT, msg, ">RETR-FAIL>");
+ tipc_msg_dbg(TIPC_OUTPUT, msg, ">RETR-FAIL>");
if (l_ptr->addr) {
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 696a8633df75..38abebaae889 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -41,7 +41,9 @@
#include "bearer.h"
-void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str)
+#ifdef CONFIG_TIPC_DEBUG
+
+void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
{
u32 usr = msg_user(msg);
tipc_printf(buf, str);
@@ -315,9 +317,11 @@ void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str
}
tipc_printf(buf, "\n");
if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) {
- tipc_msg_print(buf,msg_get_wrapped(msg)," /");
+ tipc_msg_dbg(buf, msg_get_wrapped(msg), " /");
}
if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) {
- tipc_msg_print(buf,msg_get_wrapped(msg)," /");
+ tipc_msg_dbg(buf, msg_get_wrapped(msg), " /");
}
}
+
+#endif
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 39fd1619febf..aecba5cd87d6 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -41,9 +41,6 @@
#include "msg.h"
#include "name_distr.h"
-#undef DBG_OUTPUT
-#define DBG_OUTPUT NULL
-
#define ITEM_SIZE sizeof(struct distr_item)
/**
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index ac7dfdda7973..892373e498e4 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -1050,15 +1050,12 @@ void tipc_nametbl_dump(void)
int tipc_nametbl_init(void)
{
- int array_size = sizeof(struct hlist_head) * tipc_nametbl_size;
-
- table.types = kzalloc(array_size, GFP_ATOMIC);
+ table.types = kcalloc(tipc_nametbl_size, sizeof(struct hlist_head),
+ GFP_ATOMIC);
if (!table.types)
return -ENOMEM;
- write_lock_bh(&tipc_nametbl_lock);
table.local_publ_count = 0;
- write_unlock_bh(&tipc_nametbl_lock);
return 0;
}
diff --git a/net/tipc/port.c b/net/tipc/port.c
index 2f5806410c64..757de38fe6af 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -211,15 +211,18 @@ exit:
}
/**
- * tipc_createport_raw - create a native TIPC port
+ * tipc_createport_raw - create a generic TIPC port
*
- * Returns local port reference
+ * Returns port reference, or 0 if unable to create it
+ *
+ * Note: The newly created port is returned in the locked state.
*/
u32 tipc_createport_raw(void *usr_handle,
u32 (*dispatcher)(struct tipc_port *, struct sk_buff *),
void (*wakeup)(struct tipc_port *),
- const u32 importance)
+ const u32 importance,
+ struct tipc_port **tp_ptr)
{
struct port *p_ptr;
struct tipc_msg *msg;
@@ -237,7 +240,6 @@ u32 tipc_createport_raw(void *usr_handle,
return 0;
}
- tipc_port_lock(ref);
p_ptr->publ.usr_handle = usr_handle;
p_ptr->publ.max_pkt = MAX_PKT_DEFAULT;
p_ptr->publ.ref = ref;
@@ -262,7 +264,7 @@ u32 tipc_createport_raw(void *usr_handle,
INIT_LIST_HEAD(&p_ptr->port_list);
list_add_tail(&p_ptr->port_list, &ports);
spin_unlock_bh(&tipc_port_list_lock);
- tipc_port_unlock(p_ptr);
+ *tp_ptr = &p_ptr->publ;
return ref;
}
@@ -1053,6 +1055,7 @@ int tipc_createport(u32 user_ref,
{
struct user_port *up_ptr;
struct port *p_ptr;
+ struct tipc_port *tp_ptr;
u32 ref;
up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC);
@@ -1060,12 +1063,13 @@ int tipc_createport(u32 user_ref,
warn("Port creation failed, no memory\n");
return -ENOMEM;
}
- ref = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, importance);
- p_ptr = tipc_port_lock(ref);
- if (!p_ptr) {
+ ref = tipc_createport_raw(NULL, port_dispatcher, port_wakeup,
+ importance, &tp_ptr);
+ if (ref == 0) {
kfree(up_ptr);
return -ENOMEM;
}
+ p_ptr = (struct port *)tp_ptr;
p_ptr->user_port = up_ptr;
up_ptr->user_ref = user_ref;
diff --git a/net/tipc/ref.c b/net/tipc/ref.c
index 89cbab24d08f..a101de86824d 100644
--- a/net/tipc/ref.c
+++ b/net/tipc/ref.c
@@ -142,9 +142,13 @@ void tipc_ref_table_stop(void)
/**
* tipc_ref_acquire - create reference to an object
*
- * Return a unique reference value which can be translated back to the pointer
- * 'object' at a later time. Also, pass back a pointer to the lock protecting
- * the object, but without locking it.
+ * Register an object pointer in reference table and lock the object.
+ * Returns a unique reference value that is used from then on to retrieve the
+ * object pointer, or to determine that the object has been deregistered.
+ *
+ * Note: The object is returned in the locked state so that the caller can
+ * register a partially initialized object, without running the risk that
+ * the object will be accessed before initialization is complete.
*/
u32 tipc_ref_acquire(void *object, spinlock_t **lock)
@@ -178,13 +182,13 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
ref = (next_plus_upper & ~index_mask) + index;
entry->ref = ref;
entry->object = object;
- spin_unlock_bh(&entry->lock);
*lock = &entry->lock;
}
else if (tipc_ref_table.init_point < tipc_ref_table.capacity) {
index = tipc_ref_table.init_point++;
entry = &(tipc_ref_table.entries[index]);
spin_lock_init(&entry->lock);
+ spin_lock_bh(&entry->lock);
ref = tipc_ref_table.start_mask + index;
entry->ref = ref;
entry->object = object;
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 230f9ca2ad6b..38f48795b40e 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -188,6 +188,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
const struct proto_ops *ops;
socket_state state;
struct sock *sk;
+ struct tipc_port *tp_ptr;
u32 portref;
/* Validate arguments */
@@ -225,7 +226,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
/* Allocate TIPC port for socket to use */
portref = tipc_createport_raw(sk, &dispatch, &wakeupdispatch,
- TIPC_LOW_IMPORTANCE);
+ TIPC_LOW_IMPORTANCE, &tp_ptr);
if (unlikely(portref == 0)) {
sk_free(sk);
return -ENOMEM;
@@ -241,6 +242,8 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
sk->sk_backlog_rcv = backlog_rcv;
tipc_sk(sk)->p = tipc_get_port(portref);
+ spin_unlock_bh(tp_ptr->lock);
+
if (sock->state == SS_READY) {
tipc_set_portunreturnable(portref, 1);
if (sock->type == SOCK_DGRAM)
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index 8c01ccd3626c..8f8d0a6c1c16 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -474,6 +474,7 @@ static void subscr_named_msg_event(void *usr_handle,
kfree(subscriber);
return;
}
+ spin_unlock_bh(subscriber->lock);
/* Establish a connection to subscriber */