Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (25 commits)
  smc91c92_cs: define multicast_table as unsigned char
  can: avoids a false warning
  e1000e: stop cleaning when we reach tx_ring->next_to_use
  igb: restrict WoL for 82576 ET2 Quad Port Server Adapter
  virtio_net: missing sg_init_table
  Revert "tcp: Set CHECKSUM_UNNECESSARY in tcp_init_nondata_skb"
  iwlwifi: need check for valid qos packet before free
  tcp: Set CHECKSUM_UNNECESSARY in tcp_init_nondata_skb
  udp: fix for unicast RX path optimization
  myri10ge: fix rx_pause in myri10ge_set_pauseparam
  net: corrected documentation for hardware time stamping
  stmmac: use resource_size()
  x.25 attempts to negotiate invalid throughput
  x25: Patch to fix bug 15678 - x25 accesses fields beyond end of packet.
  bridge: Fix IGMP3 report parsing
  cnic: Fix crash during bnx2x MTU change.
  qlcnic: fix set mac addr
  r6040: fix r6040_multicast_list
  vhost-net: fix vq_memory_access_ok error checking
  ath9k: fix double calls to ath_radio_enable
  ...
This commit is contained in:
Linus Torvalds 2010-04-13 11:32:48 -07:00
commit 465de2ba71
30 changed files with 348 additions and 138 deletions

View file

@ -41,11 +41,12 @@ SOF_TIMESTAMPING_SOFTWARE: return system time stamp generated in
SOF_TIMESTAMPING_TX/RX determine how time stamps are generated.
SOF_TIMESTAMPING_RAW/SYS determine how they are reported in the
following control message:
struct scm_timestamping {
struct timespec systime;
struct timespec hwtimetrans;
struct timespec hwtimeraw;
};
struct scm_timestamping {
struct timespec systime;
struct timespec hwtimetrans;
struct timespec hwtimeraw;
};
recvmsg() can be used to get this control message for regular incoming
packets. For send time stamps the outgoing packet is looped back to
@ -87,12 +88,13 @@ by the network device and will be empty without that support.
SIOCSHWTSTAMP:
Hardware time stamping must also be initialized for each device driver
that is expected to do hardware time stamping. The parameter is:
that is expected to do hardware time stamping. The parameter is defined in
/include/linux/net_tstamp.h as:
struct hwtstamp_config {
int flags; /* no flags defined right now, must be zero */
int tx_type; /* HWTSTAMP_TX_* */
int rx_filter; /* HWTSTAMP_FILTER_* */
int flags; /* no flags defined right now, must be zero */
int tx_type; /* HWTSTAMP_TX_* */
int rx_filter; /* HWTSTAMP_FILTER_* */
};
Desired behavior is passed into the kernel and to a specific device by
@ -139,42 +141,56 @@ enum {
/* time stamp any incoming packet */
HWTSTAMP_FILTER_ALL,
/* return value: time stamp all packets requested plus some others */
HWTSTAMP_FILTER_SOME,
/* return value: time stamp all packets requested plus some others */
HWTSTAMP_FILTER_SOME,
/* PTP v1, UDP, any kind of event packet */
HWTSTAMP_FILTER_PTP_V1_L4_EVENT,
...
/* for the complete list of values, please check
* the include file /include/linux/net_tstamp.h
*/
};
DEVICE IMPLEMENTATION
A driver which supports hardware time stamping must support the
SIOCSHWTSTAMP ioctl. Time stamps for received packets must be stored
in the skb with skb_hwtstamp_set().
SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with
the actual values as described in the section on SIOCSHWTSTAMP.
Time stamps for received packets must be stored in the skb. To get a pointer
to the shared time stamp structure of the skb call skb_hwtstamps(). Then
set the time stamps in the structure:
struct skb_shared_hwtstamps {
/* hardware time stamp transformed into duration
* since arbitrary point in time
*/
ktime_t hwtstamp;
ktime_t syststamp; /* hwtstamp transformed to system time base */
};
Time stamps for outgoing packets are to be generated as follows:
- In hard_start_xmit(), check if skb_hwtstamp_check_tx_hardware()
returns non-zero. If yes, then the driver is expected
to do hardware time stamping.
- In hard_start_xmit(), check if skb_tx(skb)->hardware is set no-zero.
If yes, then the driver is expected to do hardware time stamping.
- If this is possible for the skb and requested, then declare
that the driver is doing the time stamping by calling
skb_hwtstamp_tx_in_progress(). A driver not supporting
hardware time stamping doesn't do that. A driver must never
touch sk_buff::tstamp! It is used to store how time stamping
for an outgoing packets is to be done.
that the driver is doing the time stamping by setting the field
skb_tx(skb)->in_progress non-zero. You might want to keep a pointer
to the associated skb for the next step and not free the skb. A driver
not supporting hardware time stamping doesn't do that. A driver must
never touch sk_buff::tstamp! It is used to store software generated
time stamps by the network subsystem.
- As soon as the driver has sent the packet and/or obtained a
hardware time stamp for it, it passes the time stamp back by
calling skb_hwtstamp_tx() with the original skb, the raw
hardware time stamp and a handle to the device (necessary
to convert the hardware time stamp to system time). If obtaining
the hardware time stamp somehow fails, then the driver should
not fall back to software time stamping. The rationale is that
this would occur at a later time in the processing pipeline
than other software time stamping and therefore could lead
to unexpected deltas between time stamps.
- If the driver did not call skb_hwtstamp_tx_in_progress(), then
hardware time stamp. skb_hwtstamp_tx() clones the original skb and
adds the timestamps, therefore the original skb has to be freed now.
If obtaining the hardware time stamp somehow fails, then the driver
should not fall back to software time stamping. The rationale is that
this would occur at a later time in the processing pipeline than other
software time stamping and therefore could lead to unexpected deltas
between time stamps.
- If the driver did not call set skb_tx(skb)->in_progress, then
dev_hard_start_xmit() checks whether software time stamping
is wanted as fallback and potentially generates the time stamp.

View file

@ -2334,13 +2334,13 @@ static int cnic_service_bnx2x(void *data, void *status_blk)
struct cnic_local *cp = dev->cnic_priv;
u16 prod = cp->kcq_prod_idx & MAX_KCQ_IDX;
prefetch(cp->status_blk.bnx2x);
prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]);
if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) {
prefetch(cp->status_blk.bnx2x);
prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]);
if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags)))
tasklet_schedule(&cp->cnic_irq_task);
cnic_chk_pkt_rings(cp);
cnic_chk_pkt_rings(cp);
}
return 0;
}

View file

@ -661,6 +661,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
i = 0;
}
if (i == tx_ring->next_to_use)
break;
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
}

View file

@ -1814,6 +1814,7 @@ static int igb_wol_exclusion(struct igb_adapter *adapter,
retval = 0;
break;
case E1000_DEV_ID_82576_QUAD_COPPER:
case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
/* quad port adapters only support WoL on port A */
if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) {
wol->supported = 0;

View file

@ -1612,6 +1612,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
adapter->eeprom_wol = 0;
break;
case E1000_DEV_ID_82576_QUAD_COPPER:
case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
/* if quad port adapter, disable WoL on all but port A */
if (global_quad_port_a != 0)
adapter->eeprom_wol = 0;

View file

@ -1690,7 +1690,7 @@ myri10ge_set_pauseparam(struct net_device *netdev,
if (pause->tx_pause != mgp->pause)
return myri10ge_change_pause(mgp, pause->tx_pause);
if (pause->rx_pause != mgp->pause)
return myri10ge_change_pause(mgp, pause->tx_pause);
return myri10ge_change_pause(mgp, pause->rx_pause);
if (pause->autoneg != 0)
return -EINVAL;
return 0;

View file

@ -1608,9 +1608,12 @@ static void set_rx_mode(struct net_device *dev)
{
unsigned int ioaddr = dev->base_addr;
struct smc_private *smc = netdev_priv(dev);
u_int multicast_table[ 2 ] = { 0, };
unsigned char multicast_table[8];
unsigned long flags;
u_short rx_cfg_setting;
int i;
memset(multicast_table, 0, sizeof(multicast_table));
if (dev->flags & IFF_PROMISC) {
rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti;
@ -1622,10 +1625,6 @@ static void set_rx_mode(struct net_device *dev)
netdev_for_each_mc_addr(mc_addr, dev) {
u_int position = ether_crc(6, mc_addr->dmi_addr);
#ifndef final_version /* Verify multicast address. */
if ((mc_addr->dmi_addr[0] & 1) == 0)
continue;
#endif
multicast_table[position >> 29] |= 1 << ((position >> 26) & 7);
}
}
@ -1635,8 +1634,8 @@ static void set_rx_mode(struct net_device *dev)
/* Load MC table and Rx setting into the chip without interrupts. */
spin_lock_irqsave(&smc->lock, flags);
SMC_SELECT_BANK(3);
outl(multicast_table[0], ioaddr + MULTICAST0);
outl(multicast_table[1], ioaddr + MULTICAST4);
for (i = 0; i < 8; i++)
outb(multicast_table[i], ioaddr + MULTICAST0 + i);
SMC_SELECT_BANK(0);
outw(rx_cfg_setting, ioaddr + RCR);
SMC_SELECT_BANK(2);

View file

@ -431,6 +431,9 @@ void qlcnic_set_multi(struct net_device *netdev)
u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
u32 mode = VPORT_MISS_MODE_DROP;
if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
return;
qlcnic_nic_add_mac(adapter, adapter->mac_addr);
qlcnic_nic_add_mac(adapter, bcast_addr);

View file

@ -134,7 +134,7 @@
#define RX_DESC_SIZE (RX_DCNT * sizeof(struct r6040_descriptor))
#define TX_DESC_SIZE (TX_DCNT * sizeof(struct r6040_descriptor))
#define MBCR_DEFAULT 0x012A /* MAC Bus Control Register */
#define MCAST_MAX 4 /* Max number multicast addresses to filter */
#define MCAST_MAX 3 /* Max number multicast addresses to filter */
/* Descriptor status */
#define DSC_OWNER_MAC 0x8000 /* MAC is the owner of this descriptor */
@ -982,9 +982,6 @@ static void r6040_multicast_list(struct net_device *dev)
crc >>= 26;
hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
}
/* Write the index of the hash table */
for (i = 0; i < 4; i++)
iowrite16(hash_table[i] << 14, ioaddr + MCR1);
/* Fill the MAC hash tables with their values */
iowrite16(hash_table[0], ioaddr + MAR0);
iowrite16(hash_table[1], ioaddr + MAR1);
@ -1000,9 +997,9 @@ static void r6040_multicast_list(struct net_device *dev)
iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
} else {
iowrite16(0xffff, ioaddr + MID_0L + 8 * i);
iowrite16(0xffff, ioaddr + MID_0M + 8 * i);
iowrite16(0xffff, ioaddr + MID_0H + 8 * i);
iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
}
i++;
}

View file

@ -1686,7 +1686,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
}
pr_info("done!\n");
if (!request_mem_region(res->start, (res->end - res->start),
if (!request_mem_region(res->start, resource_size(res),
pdev->name)) {
pr_err("%s: ERROR: memory allocation failed"
"cannot get the I/O addr 0x%x\n",
@ -1695,9 +1695,9 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
goto out;
}
addr = ioremap(res->start, (res->end - res->start));
addr = ioremap(res->start, resource_size(res));
if (!addr) {
pr_err("%s: ERROR: memory mapping failed \n", __func__);
pr_err("%s: ERROR: memory mapping failed\n", __func__);
ret = -ENOMEM;
goto out;
}
@ -1775,7 +1775,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
out:
if (ret < 0) {
platform_set_drvdata(pdev, NULL);
release_mem_region(res->start, (res->end - res->start));
release_mem_region(res->start, resource_size(res));
if (addr != NULL)
iounmap(addr);
}
@ -1813,7 +1813,7 @@ static int stmmac_dvr_remove(struct platform_device *pdev)
iounmap((void *)ndev->base_addr);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, (res->end - res->start));
release_mem_region(res->start, resource_size(res));
free_netdev(ndev);

View file

@ -327,6 +327,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
struct scatterlist sg[2];
int err;
sg_init_table(sg, 2);
skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN);
if (unlikely(!skb))
return -ENOMEM;
@ -352,6 +353,7 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
char *p;
int i, err, offset;
sg_init_table(sg, MAX_SKB_FRAGS + 2);
/* page in sg[MAX_SKB_FRAGS + 1] is list tail */
for (i = MAX_SKB_FRAGS + 1; i > 1; --i) {
first = get_a_page(vi, gfp);

View file

@ -1532,8 +1532,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
all_wiphys_idle = ath9k_all_wiphys_idle(sc);
ath9k_set_wiphy_idle(aphy, idle);
if (!idle && all_wiphys_idle)
enable_radio = true;
enable_radio = (!idle && all_wiphys_idle);
/*
* After we unlock here its possible another wiphy

View file

@ -2015,7 +2015,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn "
"%d index %d\n", scd_ssn , index);
freed = iwl_tx_queue_reclaim(priv, txq_id, index);
iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
if (qc)
iwl_free_tfds_in_queue(priv, sta_id,
tid, freed);
if (priv->mac80211_registered &&
(iwl_queue_space(&txq->q) > txq->q.low_mark) &&
@ -2041,14 +2043,17 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
tx_resp->failure_frame);
freed = iwl_tx_queue_reclaim(priv, txq_id, index);
iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
if (qc && likely(sta_id != IWL_INVALID_STATION))
iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
else if (sta_id == IWL_INVALID_STATION)
IWL_DEBUG_TX_REPLY(priv, "Station not known\n");
if (priv->mac80211_registered &&
(iwl_queue_space(&txq->q) > txq->q.low_mark))
iwl_wake_queue(priv, txq_id);
}
iwl_txq_check_empty(priv, sta_id, tid, txq_id);
if (qc && likely(sta_id != IWL_INVALID_STATION))
iwl_txq_check_empty(priv, sta_id, tid, txq_id);
if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n");

View file

@ -346,6 +346,17 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
!!(rate_n_flags & RATE_MCS_ANT_C_MSK);
}
/*
* Static function to get the expected throughput from an iwl_scale_tbl_info
* that wraps a NULL pointer check
*/
static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
{
if (tbl->expected_tpt)
return tbl->expected_tpt[rs_index];
return 0;
}
/**
* rs_collect_tx_data - Update the success/failure sliding window
*
@ -353,19 +364,21 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
* at this rate. window->data contains the bitmask of successful
* packets.
*/
static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
int scale_index, s32 tpt, int attempts,
int successes)
static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
int scale_index, int attempts, int successes)
{
struct iwl_rate_scale_data *window = NULL;
static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1));
s32 fail_count;
s32 fail_count, tpt;
if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
return -EINVAL;
/* Select window for current tx bit rate */
window = &(windows[scale_index]);
window = &(tbl->win[scale_index]);
/* Get expected throughput */
tpt = get_expected_tpt(tbl, scale_index);
/*
* Keep track of only the latest 62 tx frame attempts in this rate's
@ -739,16 +752,6 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a,
return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) &&
(a->is_SGI == b->is_SGI);
}
/*
* Static function to get the expected throughput from an iwl_scale_tbl_info
* that wraps a NULL pointer check
*/
static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
{
if (tbl->expected_tpt)
return tbl->expected_tpt[rs_index];
return 0;
}
/*
* mac80211 sends us Tx status
@ -765,12 +768,10 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_rate_scale_data *window = NULL;
enum mac80211_rate_control_flags mac_flags;
u32 tx_rate;
struct iwl_scale_tbl_info tbl_type;
struct iwl_scale_tbl_info *curr_tbl, *other_tbl;
s32 tpt = 0;
struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
@ -853,7 +854,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n");
return;
}
window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]);
/*
* Updating the frame history depends on whether packets were
@ -866,8 +866,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
&rs_index);
tpt = get_expected_tpt(curr_tbl, rs_index);
rs_collect_tx_data(window, rs_index, tpt,
rs_collect_tx_data(curr_tbl, rs_index,
info->status.ampdu_ack_len,
info->status.ampdu_ack_map);
@ -897,19 +896,13 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
* table as active/search.
*/
if (table_type_matches(&tbl_type, curr_tbl))
tpt = get_expected_tpt(curr_tbl, rs_index);
tmp_tbl = curr_tbl;
else if (table_type_matches(&tbl_type, other_tbl))
tpt = get_expected_tpt(other_tbl, rs_index);
tmp_tbl = other_tbl;
else
continue;
/* Constants mean 1 transmission, 0 successes */
if (i < retries)
rs_collect_tx_data(window, rs_index, tpt, 1,
0);
else
rs_collect_tx_data(window, rs_index, tpt, 1,
legacy_success);
rs_collect_tx_data(tmp_tbl, rs_index, 1,
i < retries ? 0 : legacy_success);
}
/* Update success/fail counts if not searching for new mode */

View file

@ -308,10 +308,13 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
/* Allocate and init all Tx and Command queues */
ret = iwl_txq_ctx_reset(priv);
if (ret)
return ret;
/* Allocate or reset and init all Tx and Command queues */
if (!priv->txq) {
ret = iwl_txq_ctx_alloc(priv);
if (ret)
return ret;
} else
iwl_txq_ctx_reset(priv);
set_bit(STATUS_INIT, &priv->status);

View file

@ -442,7 +442,8 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
/*****************************************************
* TX
******************************************************/
int iwl_txq_ctx_reset(struct iwl_priv *priv);
int iwl_txq_ctx_alloc(struct iwl_priv *priv);
void iwl_txq_ctx_reset(struct iwl_priv *priv);
void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
@ -456,6 +457,8 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv,
void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
int slots_num, u32 txq_id);
void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
int slots_num, u32 txq_id);
void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn);
int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid);

View file

@ -194,10 +194,34 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
struct iwl_queue *q = &txq->q;
struct device *dev = &priv->pci_dev->dev;
int i;
bool huge = false;
if (q->n_bd == 0)
return;
for (; q->read_ptr != q->write_ptr;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
/* we have no way to tell if it is a huge cmd ATM */
i = get_cmd_index(q, q->read_ptr, 0);
if (txq->meta[i].flags & CMD_SIZE_HUGE) {
huge = true;
continue;
}
pci_unmap_single(priv->pci_dev,
pci_unmap_addr(&txq->meta[i], mapping),
pci_unmap_len(&txq->meta[i], len),
PCI_DMA_BIDIRECTIONAL);
}
if (huge) {
i = q->n_window;
pci_unmap_single(priv->pci_dev,
pci_unmap_addr(&txq->meta[i], mapping),
pci_unmap_len(&txq->meta[i], len),
PCI_DMA_BIDIRECTIONAL);
}
/* De-alloc array of command/tx buffers */
for (i = 0; i <= TFD_CMD_SLOTS; i++)
kfree(txq->cmd[i]);
@ -410,6 +434,26 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
}
EXPORT_SYMBOL(iwl_tx_queue_init);
void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
int slots_num, u32 txq_id)
{
int actual_slots = slots_num;
if (txq_id == IWL_CMD_QUEUE_NUM)
actual_slots++;
memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots);
txq->need_update = 0;
/* Initialize queue's high/low-water marks, and head/tail indexes */
iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
/* Tell device where to find queue */
priv->cfg->ops->lib->txq_init(priv, txq);
}
EXPORT_SYMBOL(iwl_tx_queue_reset);
/**
* iwl_hw_txq_ctx_free - Free TXQ Context
*
@ -421,8 +465,7 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
/* Tx queues */
if (priv->txq) {
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
txq_id++)
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
if (txq_id == IWL_CMD_QUEUE_NUM)
iwl_cmd_queue_free(priv);
else
@ -438,15 +481,15 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
/**
* iwl_txq_ctx_reset - Reset TX queue context
* Destroys all DMA structures and initialize them again
* iwl_txq_ctx_alloc - allocate TX queue context
* Allocate all Tx DMA structures and initialize them
*
* @param priv
* @return error code
*/
int iwl_txq_ctx_reset(struct iwl_priv *priv)
int iwl_txq_ctx_alloc(struct iwl_priv *priv)
{
int ret = 0;
int ret;
int txq_id, slots_num;
unsigned long flags;
@ -504,8 +547,31 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
return ret;
}
void iwl_txq_ctx_reset(struct iwl_priv *priv)
{
int txq_id, slots_num;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
/* Turn off all Tx DMA fifos */
priv->cfg->ops->lib->txq_set_sched(priv, 0);
/* Tell NIC where to find the "keep warm" buffer */
iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
spin_unlock_irqrestore(&priv->lock, flags);
/* Alloc and init all Tx queues, including the command queue (#4) */
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
slots_num = txq_id == IWL_CMD_QUEUE_NUM ?
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
}
}
/**
* iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory
* iwl_txq_ctx_stop - Stop all Tx DMA channels
*/
void iwl_txq_ctx_stop(struct iwl_priv *priv)
{
@ -525,9 +591,6 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv)
1000);
}
spin_unlock_irqrestore(&priv->lock, flags);
/* Deallocate memory for all Tx queues */
iwl_hw_txq_ctx_free(priv);
}
EXPORT_SYMBOL(iwl_txq_ctx_stop);
@ -1050,6 +1113,14 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
spin_lock_irqsave(&priv->hcmd_lock, flags);
/* If this is a huge cmd, mark the huge flag also on the meta.flags
* of the _original_ cmd. This is used for DMA mapping clean up.
*/
if (cmd->flags & CMD_SIZE_HUGE) {
idx = get_cmd_index(q, q->write_ptr, 0);
txq->meta[idx].flags = CMD_SIZE_HUGE;
}
idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
out_cmd = txq->cmd[idx];
out_meta = &txq->meta[idx];
@ -1227,6 +1298,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
struct iwl_device_cmd *cmd;
struct iwl_cmd_meta *meta;
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
@ -1240,9 +1312,17 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
return;
}
cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index];
/* If this is a huge cmd, clear the huge flag on the meta.flags
* of the _original_ cmd. So that iwl_cmd_queue_free won't unmap
* the DMA buffer for the scan (huge) command.
*/
if (huge) {
cmd_index = get_cmd_index(&txq->q, index, 0);
txq->meta[cmd_index].flags = 0;
}
cmd_index = get_cmd_index(&txq->q, index, huge);
cmd = txq->cmd[cmd_index];
meta = &txq->meta[cmd_index];
pci_unmap_single(priv->pci_dev,
pci_unmap_addr(meta, mapping),
@ -1264,6 +1344,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
get_cmd_string(cmd->hdr.cmd));
wake_up_interruptible(&priv->wait_command_queue);
}
meta->flags = 0;
}
EXPORT_SYMBOL(iwl_tx_cmd_complete);

View file

@ -236,6 +236,10 @@ static int vq_memory_access_ok(void __user *log_base, struct vhost_memory *mem,
int log_all)
{
int i;
if (!mem)
return 0;
for (i = 0; i < mem->nregions; ++i) {
struct vhost_memory_region *m = mem->regions + i;
unsigned long a = m->userspace_addr;

View file

@ -183,6 +183,10 @@ extern int sysctl_x25_clear_request_timeout;
extern int sysctl_x25_ack_holdback_timeout;
extern int sysctl_x25_forward;
extern int x25_parse_address_block(struct sk_buff *skb,
struct x25_address *called_addr,
struct x25_address *calling_addr);
extern int x25_addr_ntoa(unsigned char *, struct x25_address *,
struct x25_address *);
extern int x25_addr_aton(unsigned char *, struct x25_address *,

View file

@ -723,7 +723,7 @@ static int br_multicast_igmp3_report(struct net_bridge *br,
if (!pskb_may_pull(skb, len))
return -EINVAL;
grec = (void *)(skb->data + len);
grec = (void *)(skb->data + len - sizeof(*grec));
group = grec->grec_mca;
type = grec->grec_type;

View file

@ -445,7 +445,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
return -EFAULT;
}
} else if (count == 1) {
if (copy_from_user(&sfilter, optval, optlen))
if (copy_from_user(&sfilter, optval, sizeof(sfilter)))
return -EFAULT;
}

View file

@ -472,8 +472,8 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
if (hslot->count < hslot2->count)
goto begin;
result = udp4_lib_lookup2(net, INADDR_ANY, sport,
daddr, hnum, dif,
result = udp4_lib_lookup2(net, saddr, sport,
INADDR_ANY, hnum, dif,
hslot2, slot2);
}
rcu_read_unlock();

View file

@ -259,8 +259,8 @@ static struct sock *__udp6_lib_lookup(struct net *net,
if (hslot->count < hslot2->count)
goto begin;
result = udp6_lib_lookup2(net, &in6addr_any, sport,
daddr, hnum, dif,
result = udp6_lib_lookup2(net, saddr, sport,
&in6addr_any, hnum, dif,
hslot2, slot2);
}
rcu_read_unlock();

View file

@ -225,11 +225,11 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP:
sdata->vif.bss_conf.enable_beacon =
!!rcu_dereference(sdata->u.ap.beacon);
!!sdata->u.ap.beacon;
break;
case NL80211_IFTYPE_ADHOC:
sdata->vif.bss_conf.enable_beacon =
!!rcu_dereference(sdata->u.ibss.presp);
!!sdata->u.ibss.presp;
break;
case NL80211_IFTYPE_MESH_POINT:
sdata->vif.bss_conf.enable_beacon = true;

View file

@ -750,9 +750,6 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_ACTION:
if (skb->len < IEEE80211_MIN_ACTION_SIZE)
return RX_DROP_MONITOR;
/* fall through */
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_BEACON:
skb_queue_tail(&ifmsh->skb_queue, skb);

View file

@ -1974,6 +1974,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
goto handled;
}
break;
case MESH_PLINK_CATEGORY:
case MESH_PATH_SEL_CATEGORY:
if (ieee80211_vif_is_mesh(&sdata->vif))
return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
break;
}
/*

View file

@ -93,12 +93,18 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
rcu_read_lock_held() ||
lockdep_is_held(&local->sta_lock) ||
lockdep_is_held(&local->sta_mtx));
while (sta) {
if (sta->sdata == sdata &&
memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
break;
sta = rcu_dereference(sta->hnext);
sta = rcu_dereference_check(sta->hnext,
rcu_read_lock_held() ||
lockdep_is_held(&local->sta_lock) ||
lockdep_is_held(&local->sta_mtx));
}
return sta;
}
@ -113,13 +119,19 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
rcu_read_lock_held() ||
lockdep_is_held(&local->sta_lock) ||
lockdep_is_held(&local->sta_mtx));
while (sta) {
if ((sta->sdata == sdata ||
sta->sdata->bss == sdata->bss) &&
memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
break;
sta = rcu_dereference(sta->hnext);
sta = rcu_dereference_check(sta->hnext,
rcu_read_lock_held() ||
lockdep_is_held(&local->sta_lock) ||
lockdep_is_held(&local->sta_mtx));
}
return sta;
}

View file

@ -83,6 +83,41 @@ struct compat_x25_subscrip_struct {
};
#endif
int x25_parse_address_block(struct sk_buff *skb,
struct x25_address *called_addr,
struct x25_address *calling_addr)
{
unsigned char len;
int needed;
int rc;
if (skb->len < 1) {
/* packet has no address block */
rc = 0;
goto empty;
}
len = *skb->data;
needed = 1 + (len >> 4) + (len & 0x0f);
if (skb->len < needed) {
/* packet is too short to hold the addresses it claims
to hold */
rc = -1;
goto empty;
}
return x25_addr_ntoa(skb->data, called_addr, calling_addr);
empty:
*called_addr->x25_addr = 0;
*calling_addr->x25_addr = 0;
return rc;
}
int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr,
struct x25_address *calling_addr)
{
@ -554,7 +589,8 @@ static int x25_create(struct net *net, struct socket *sock, int protocol,
x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;
x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE;
x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;
x25->facilities.throughput = X25_DEFAULT_THROUGHPUT;
x25->facilities.throughput = 0; /* by default don't negotiate
throughput */
x25->facilities.reverse = X25_DEFAULT_REVERSE;
x25->dte_facilities.calling_len = 0;
x25->dte_facilities.called_len = 0;
@ -922,16 +958,26 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
/*
* Extract the X.25 addresses and convert them to ASCII strings,
* and remove them.
*
* Address block is mandatory in call request packets
*/
addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr);
addr_len = x25_parse_address_block(skb, &source_addr, &dest_addr);
if (addr_len <= 0)
goto out_clear_request;
skb_pull(skb, addr_len);
/*
* Get the length of the facilities, skip past them for the moment
* get the call user data because this is needed to determine
* the correct listener
*
* Facilities length is mandatory in call request packets
*/
if (skb->len < 1)
goto out_clear_request;
len = skb->data[0] + 1;
if (skb->len < len)
goto out_clear_request;
skb_pull(skb,len);
/*
@ -1415,9 +1461,20 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
if (facilities.winsize_in < 1 ||
facilities.winsize_in > 127)
break;
if (facilities.throughput < 0x03 ||
facilities.throughput > 0xDD)
break;
if (facilities.throughput) {
int out = facilities.throughput & 0xf0;
int in = facilities.throughput & 0x0f;
if (!out)
facilities.throughput |=
X25_DEFAULT_THROUGHPUT << 4;
else if (out < 0x30 || out > 0xD0)
break;
if (!in)
facilities.throughput |=
X25_DEFAULT_THROUGHPUT;
else if (in < 0x03 || in > 0x0D)
break;
}
if (facilities.reverse &&
(facilities.reverse & 0x81) != 0x81)
break;

View file

@ -35,7 +35,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask)
{
unsigned char *p = skb->data;
unsigned int len = *p++;
unsigned int len;
*vc_fac_mask = 0;
@ -50,6 +50,14 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae));
memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae));
if (skb->len < 1)
return 0;
len = *p++;
if (len >= skb->len)
return -1;
while (len > 0) {
switch (*p & X25_FAC_CLASS_MASK) {
case X25_FAC_CLASS_A:
@ -247,6 +255,8 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
memcpy(new, ours, sizeof(*new));
len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask);
if (len < 0)
return len;
/*
* They want reverse charging, we won't accept it.
@ -259,9 +269,18 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
new->reverse = theirs.reverse;
if (theirs.throughput) {
if (theirs.throughput < ours->throughput) {
SOCK_DEBUG(sk, "X.25: throughput negotiated down\n");
new->throughput = theirs.throughput;
int theirs_in = theirs.throughput & 0x0f;
int theirs_out = theirs.throughput & 0xf0;
int ours_in = ours->throughput & 0x0f;
int ours_out = ours->throughput & 0xf0;
if (!ours_in || theirs_in < ours_in) {
SOCK_DEBUG(sk, "X.25: inbound throughput negotiated\n");
new->throughput = (new->throughput & 0xf0) | theirs_in;
}
if (!ours_out || theirs_out < ours_out) {
SOCK_DEBUG(sk,
"X.25: outbound throughput negotiated\n");
new->throughput = (new->throughput & 0x0f) | theirs_out;
}
}

View file

@ -90,6 +90,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
{
struct x25_address source_addr, dest_addr;
int len;
switch (frametype) {
case X25_CALL_ACCEPTED: {
@ -107,11 +108,17 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp
* Parse the data in the frame.
*/
skb_pull(skb, X25_STD_MIN_LEN);
skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
skb_pull(skb,
x25_parse_facilities(skb, &x25->facilities,
len = x25_parse_address_block(skb, &source_addr,
&dest_addr);
if (len > 0)
skb_pull(skb, len);
len = x25_parse_facilities(skb, &x25->facilities,
&x25->dte_facilities,
&x25->vc_facil_mask));
&x25->vc_facil_mask);
if (len > 0)
skb_pull(skb, len);
/*
* Copy any Call User Data.
*/