diff options
30 files changed, 348 insertions, 138 deletions
diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt index 0e58b4539176..e8c8f4f06c67 100644 --- a/Documentation/networking/timestamping.txt +++ b/Documentation/networking/timestamping.txt | |||
| @@ -41,11 +41,12 @@ SOF_TIMESTAMPING_SOFTWARE: return system time stamp generated in | |||
| 41 | SOF_TIMESTAMPING_TX/RX determine how time stamps are generated. | 41 | SOF_TIMESTAMPING_TX/RX determine how time stamps are generated. |
| 42 | SOF_TIMESTAMPING_RAW/SYS determine how they are reported in the | 42 | SOF_TIMESTAMPING_RAW/SYS determine how they are reported in the |
| 43 | following control message: | 43 | following control message: |
| 44 | struct scm_timestamping { | 44 | |
| 45 | struct timespec systime; | 45 | struct scm_timestamping { |
| 46 | struct timespec hwtimetrans; | 46 | struct timespec systime; |
| 47 | struct timespec hwtimeraw; | 47 | struct timespec hwtimetrans; |
| 48 | }; | 48 | struct timespec hwtimeraw; |
| 49 | }; | ||
| 49 | 50 | ||
| 50 | recvmsg() can be used to get this control message for regular incoming | 51 | recvmsg() can be used to get this control message for regular incoming |
| 51 | packets. For send time stamps the outgoing packet is looped back to | 52 | 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. | |||
| 87 | SIOCSHWTSTAMP: | 88 | SIOCSHWTSTAMP: |
| 88 | 89 | ||
| 89 | Hardware time stamping must also be initialized for each device driver | 90 | Hardware time stamping must also be initialized for each device driver |
| 90 | that is expected to do hardware time stamping. The parameter is: | 91 | that is expected to do hardware time stamping. The parameter is defined in |
| 92 | /include/linux/net_tstamp.h as: | ||
| 91 | 93 | ||
| 92 | struct hwtstamp_config { | 94 | struct hwtstamp_config { |
| 93 | int flags; /* no flags defined right now, must be zero */ | 95 | int flags; /* no flags defined right now, must be zero */ |
| 94 | int tx_type; /* HWTSTAMP_TX_* */ | 96 | int tx_type; /* HWTSTAMP_TX_* */ |
| 95 | int rx_filter; /* HWTSTAMP_FILTER_* */ | 97 | int rx_filter; /* HWTSTAMP_FILTER_* */ |
| 96 | }; | 98 | }; |
| 97 | 99 | ||
| 98 | Desired behavior is passed into the kernel and to a specific device by | 100 | Desired behavior is passed into the kernel and to a specific device by |
| @@ -139,42 +141,56 @@ enum { | |||
| 139 | /* time stamp any incoming packet */ | 141 | /* time stamp any incoming packet */ |
| 140 | HWTSTAMP_FILTER_ALL, | 142 | HWTSTAMP_FILTER_ALL, |
| 141 | 143 | ||
| 142 | /* return value: time stamp all packets requested plus some others */ | 144 | /* return value: time stamp all packets requested plus some others */ |
| 143 | HWTSTAMP_FILTER_SOME, | 145 | HWTSTAMP_FILTER_SOME, |
| 144 | 146 | ||
| 145 | /* PTP v1, UDP, any kind of event packet */ | 147 | /* PTP v1, UDP, any kind of event packet */ |
| 146 | HWTSTAMP_FILTER_PTP_V1_L4_EVENT, | 148 | HWTSTAMP_FILTER_PTP_V1_L4_EVENT, |
| 147 | 149 | ||
| 148 | ... | 150 | /* for the complete list of values, please check |
| 151 | * the include file /include/linux/net_tstamp.h | ||
| 152 | */ | ||
| 149 | }; | 153 | }; |
| 150 | 154 | ||
| 151 | 155 | ||
| 152 | DEVICE IMPLEMENTATION | 156 | DEVICE IMPLEMENTATION |
| 153 | 157 | ||
| 154 | A driver which supports hardware time stamping must support the | 158 | A driver which supports hardware time stamping must support the |
| 155 | SIOCSHWTSTAMP ioctl. Time stamps for received packets must be stored | 159 | SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with |
| 156 | in the skb with skb_hwtstamp_set(). | 160 | the actual values as described in the section on SIOCSHWTSTAMP. |
| 161 | |||
| 162 | Time stamps for received packets must be stored in the skb. To get a pointer | ||
| 163 | to the shared time stamp structure of the skb call skb_hwtstamps(). Then | ||
| 164 | set the time stamps in the structure: | ||
| 165 | |||
| 166 | struct skb_shared_hwtstamps { | ||
| 167 | /* hardware time stamp transformed into duration | ||
| 168 | * since arbitrary point in time | ||
| 169 | */ | ||
| 170 | ktime_t hwtstamp; | ||
| 171 | ktime_t syststamp; /* hwtstamp transformed to system time base */ | ||
| 172 | }; | ||
| 157 | 173 | ||
| 158 | Time stamps for outgoing packets are to be generated as follows: | 174 | Time stamps for outgoing packets are to be generated as follows: |
| 159 | - In hard_start_xmit(), check if skb_hwtstamp_check_tx_hardware() | 175 | - In hard_start_xmit(), check if skb_tx(skb)->hardware is set no-zero. |
| 160 | returns non-zero. If yes, then the driver is expected | 176 | If yes, then the driver is expected to do hardware time stamping. |
| 161 | to do hardware time stamping. | ||
| 162 | - If this is possible for the skb and requested, then declare | 177 | - If this is possible for the skb and requested, then declare |
| 163 | that the driver is doing the time stamping by calling | 178 | that the driver is doing the time stamping by setting the field |
| 164 | skb_hwtstamp_tx_in_progress(). A driver not supporting | 179 | skb_tx(skb)->in_progress non-zero. You might want to keep a pointer |
| 165 | hardware time stamping doesn't do that. A driver must never | 180 | to the associated skb for the next step and not free the skb. A driver |
| 166 | touch sk_buff::tstamp! It is used to store how time stamping | 181 | not supporting hardware time stamping doesn't do that. A driver must |
| 167 | for an outgoing packets is to be done. | 182 | never touch sk_buff::tstamp! It is used to store software generated |
| 183 | time stamps by the network subsystem. | ||
| 168 | - As soon as the driver has sent the packet and/or obtained a | 184 | - As soon as the driver has sent the packet and/or obtained a |
| 169 | hardware time stamp for it, it passes the time stamp back by | 185 | hardware time stamp for it, it passes the time stamp back by |
| 170 | calling skb_hwtstamp_tx() with the original skb, the raw | 186 | calling skb_hwtstamp_tx() with the original skb, the raw |
| 171 | hardware time stamp and a handle to the device (necessary | 187 | hardware time stamp. skb_hwtstamp_tx() clones the original skb and |
| 172 | to convert the hardware time stamp to system time). If obtaining | 188 | adds the timestamps, therefore the original skb has to be freed now. |
| 173 | the hardware time stamp somehow fails, then the driver should | 189 | If obtaining the hardware time stamp somehow fails, then the driver |
| 174 | not fall back to software time stamping. The rationale is that | 190 | should not fall back to software time stamping. The rationale is that |
| 175 | this would occur at a later time in the processing pipeline | 191 | this would occur at a later time in the processing pipeline than other |
| 176 | than other software time stamping and therefore could lead | 192 | software time stamping and therefore could lead to unexpected deltas |
| 177 | to unexpected deltas between time stamps. | 193 | between time stamps. |
| 178 | - If the driver did not call skb_hwtstamp_tx_in_progress(), then | 194 | - If the driver did not call set skb_tx(skb)->in_progress, then |
| 179 | dev_hard_start_xmit() checks whether software time stamping | 195 | dev_hard_start_xmit() checks whether software time stamping |
| 180 | is wanted as fallback and potentially generates the time stamp. | 196 | is wanted as fallback and potentially generates the time stamp. |
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 9781942992e9..4b451a7c03e9 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c | |||
| @@ -2334,13 +2334,13 @@ static int cnic_service_bnx2x(void *data, void *status_blk) | |||
| 2334 | struct cnic_local *cp = dev->cnic_priv; | 2334 | struct cnic_local *cp = dev->cnic_priv; |
| 2335 | u16 prod = cp->kcq_prod_idx & MAX_KCQ_IDX; | 2335 | u16 prod = cp->kcq_prod_idx & MAX_KCQ_IDX; |
| 2336 | 2336 | ||
| 2337 | prefetch(cp->status_blk.bnx2x); | 2337 | if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) { |
| 2338 | prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]); | 2338 | prefetch(cp->status_blk.bnx2x); |
| 2339 | prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]); | ||
| 2339 | 2340 | ||
| 2340 | if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) | ||
| 2341 | tasklet_schedule(&cp->cnic_irq_task); | 2341 | tasklet_schedule(&cp->cnic_irq_task); |
| 2342 | 2342 | cnic_chk_pkt_rings(cp); | |
| 2343 | cnic_chk_pkt_rings(cp); | 2343 | } |
| 2344 | 2344 | ||
| 2345 | return 0; | 2345 | return 0; |
| 2346 | } | 2346 | } |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index cfd09cea7214..73d43c53015a 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
| @@ -661,6 +661,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) | |||
| 661 | i = 0; | 661 | i = 0; |
| 662 | } | 662 | } |
| 663 | 663 | ||
| 664 | if (i == tx_ring->next_to_use) | ||
| 665 | break; | ||
| 664 | eop = tx_ring->buffer_info[i].next_to_watch; | 666 | eop = tx_ring->buffer_info[i].next_to_watch; |
| 665 | eop_desc = E1000_TX_DESC(*tx_ring, eop); | 667 | eop_desc = E1000_TX_DESC(*tx_ring, eop); |
| 666 | } | 668 | } |
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index d313fae992da..743038490104 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c | |||
| @@ -1814,6 +1814,7 @@ static int igb_wol_exclusion(struct igb_adapter *adapter, | |||
| 1814 | retval = 0; | 1814 | retval = 0; |
| 1815 | break; | 1815 | break; |
| 1816 | case E1000_DEV_ID_82576_QUAD_COPPER: | 1816 | case E1000_DEV_ID_82576_QUAD_COPPER: |
| 1817 | case E1000_DEV_ID_82576_QUAD_COPPER_ET2: | ||
| 1817 | /* quad port adapters only support WoL on port A */ | 1818 | /* quad port adapters only support WoL on port A */ |
| 1818 | if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) { | 1819 | if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) { |
| 1819 | wol->supported = 0; | 1820 | wol->supported = 0; |
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 9b3c51ab1758..c9baa2aa98cd 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
| @@ -1612,6 +1612,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, | |||
| 1612 | adapter->eeprom_wol = 0; | 1612 | adapter->eeprom_wol = 0; |
| 1613 | break; | 1613 | break; |
| 1614 | case E1000_DEV_ID_82576_QUAD_COPPER: | 1614 | case E1000_DEV_ID_82576_QUAD_COPPER: |
| 1615 | case E1000_DEV_ID_82576_QUAD_COPPER_ET2: | ||
| 1615 | /* if quad port adapter, disable WoL on all but port A */ | 1616 | /* if quad port adapter, disable WoL on all but port A */ |
| 1616 | if (global_quad_port_a != 0) | 1617 | if (global_quad_port_a != 0) |
| 1617 | adapter->eeprom_wol = 0; | 1618 | adapter->eeprom_wol = 0; |
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 471887742b02..ecde0876a785 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
| @@ -1690,7 +1690,7 @@ myri10ge_set_pauseparam(struct net_device *netdev, | |||
| 1690 | if (pause->tx_pause != mgp->pause) | 1690 | if (pause->tx_pause != mgp->pause) |
| 1691 | return myri10ge_change_pause(mgp, pause->tx_pause); | 1691 | return myri10ge_change_pause(mgp, pause->tx_pause); |
| 1692 | if (pause->rx_pause != mgp->pause) | 1692 | if (pause->rx_pause != mgp->pause) |
| 1693 | return myri10ge_change_pause(mgp, pause->tx_pause); | 1693 | return myri10ge_change_pause(mgp, pause->rx_pause); |
| 1694 | if (pause->autoneg != 0) | 1694 | if (pause->autoneg != 0) |
| 1695 | return -EINVAL; | 1695 | return -EINVAL; |
| 1696 | return 0; | 1696 | return 0; |
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index ff7eb9116b6a..fd9d6e34fda4 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
| @@ -1608,9 +1608,12 @@ static void set_rx_mode(struct net_device *dev) | |||
| 1608 | { | 1608 | { |
| 1609 | unsigned int ioaddr = dev->base_addr; | 1609 | unsigned int ioaddr = dev->base_addr; |
| 1610 | struct smc_private *smc = netdev_priv(dev); | 1610 | struct smc_private *smc = netdev_priv(dev); |
| 1611 | u_int multicast_table[ 2 ] = { 0, }; | 1611 | unsigned char multicast_table[8]; |
| 1612 | unsigned long flags; | 1612 | unsigned long flags; |
| 1613 | u_short rx_cfg_setting; | 1613 | u_short rx_cfg_setting; |
| 1614 | int i; | ||
| 1615 | |||
| 1616 | memset(multicast_table, 0, sizeof(multicast_table)); | ||
| 1614 | 1617 | ||
| 1615 | if (dev->flags & IFF_PROMISC) { | 1618 | if (dev->flags & IFF_PROMISC) { |
| 1616 | rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti; | 1619 | rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti; |
| @@ -1622,10 +1625,6 @@ static void set_rx_mode(struct net_device *dev) | |||
| 1622 | 1625 | ||
| 1623 | netdev_for_each_mc_addr(mc_addr, dev) { | 1626 | netdev_for_each_mc_addr(mc_addr, dev) { |
| 1624 | u_int position = ether_crc(6, mc_addr->dmi_addr); | 1627 | u_int position = ether_crc(6, mc_addr->dmi_addr); |
| 1625 | #ifndef final_version /* Verify multicast address. */ | ||
| 1626 | if ((mc_addr->dmi_addr[0] & 1) == 0) | ||
| 1627 | continue; | ||
| 1628 | #endif | ||
| 1629 | multicast_table[position >> 29] |= 1 << ((position >> 26) & 7); | 1628 | multicast_table[position >> 29] |= 1 << ((position >> 26) & 7); |
| 1630 | } | 1629 | } |
| 1631 | } | 1630 | } |
| @@ -1635,8 +1634,8 @@ static void set_rx_mode(struct net_device *dev) | |||
| 1635 | /* Load MC table and Rx setting into the chip without interrupts. */ | 1634 | /* Load MC table and Rx setting into the chip without interrupts. */ |
| 1636 | spin_lock_irqsave(&smc->lock, flags); | 1635 | spin_lock_irqsave(&smc->lock, flags); |
| 1637 | SMC_SELECT_BANK(3); | 1636 | SMC_SELECT_BANK(3); |
| 1638 | outl(multicast_table[0], ioaddr + MULTICAST0); | 1637 | for (i = 0; i < 8; i++) |
| 1639 | outl(multicast_table[1], ioaddr + MULTICAST4); | 1638 | outb(multicast_table[i], ioaddr + MULTICAST0 + i); |
| 1640 | SMC_SELECT_BANK(0); | 1639 | SMC_SELECT_BANK(0); |
| 1641 | outw(rx_cfg_setting, ioaddr + RCR); | 1640 | outw(rx_cfg_setting, ioaddr + RCR); |
| 1642 | SMC_SELECT_BANK(2); | 1641 | SMC_SELECT_BANK(2); |
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index a6ef266a2fe2..e73ba455aa20 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c | |||
| @@ -431,6 +431,9 @@ void qlcnic_set_multi(struct net_device *netdev) | |||
| 431 | u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 431 | u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
| 432 | u32 mode = VPORT_MISS_MODE_DROP; | 432 | u32 mode = VPORT_MISS_MODE_DROP; |
| 433 | 433 | ||
| 434 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | ||
| 435 | return; | ||
| 436 | |||
| 434 | qlcnic_nic_add_mac(adapter, adapter->mac_addr); | 437 | qlcnic_nic_add_mac(adapter, adapter->mac_addr); |
| 435 | qlcnic_nic_add_mac(adapter, bcast_addr); | 438 | qlcnic_nic_add_mac(adapter, bcast_addr); |
| 436 | 439 | ||
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 43afdb6b25e6..0298d8c1dcb6 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c | |||
| @@ -134,7 +134,7 @@ | |||
| 134 | #define RX_DESC_SIZE (RX_DCNT * sizeof(struct r6040_descriptor)) | 134 | #define RX_DESC_SIZE (RX_DCNT * sizeof(struct r6040_descriptor)) |
| 135 | #define TX_DESC_SIZE (TX_DCNT * sizeof(struct r6040_descriptor)) | 135 | #define TX_DESC_SIZE (TX_DCNT * sizeof(struct r6040_descriptor)) |
| 136 | #define MBCR_DEFAULT 0x012A /* MAC Bus Control Register */ | 136 | #define MBCR_DEFAULT 0x012A /* MAC Bus Control Register */ |
| 137 | #define MCAST_MAX 4 /* Max number multicast addresses to filter */ | 137 | #define MCAST_MAX 3 /* Max number multicast addresses to filter */ |
| 138 | 138 | ||
| 139 | /* Descriptor status */ | 139 | /* Descriptor status */ |
| 140 | #define DSC_OWNER_MAC 0x8000 /* MAC is the owner of this descriptor */ | 140 | #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) | |||
| 982 | crc >>= 26; | 982 | crc >>= 26; |
| 983 | hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); | 983 | hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); |
| 984 | } | 984 | } |
| 985 | /* Write the index of the hash table */ | ||
| 986 | for (i = 0; i < 4; i++) | ||
| 987 | iowrite16(hash_table[i] << 14, ioaddr + MCR1); | ||
| 988 | /* Fill the MAC hash tables with their values */ | 985 | /* Fill the MAC hash tables with their values */ |
| 989 | iowrite16(hash_table[0], ioaddr + MAR0); | 986 | iowrite16(hash_table[0], ioaddr + MAR0); |
| 990 | iowrite16(hash_table[1], ioaddr + MAR1); | 987 | iowrite16(hash_table[1], ioaddr + MAR1); |
| @@ -1000,9 +997,9 @@ static void r6040_multicast_list(struct net_device *dev) | |||
| 1000 | iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); | 997 | iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); |
| 1001 | iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); | 998 | iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); |
| 1002 | } else { | 999 | } else { |
| 1003 | iowrite16(0xffff, ioaddr + MID_0L + 8 * i); | 1000 | iowrite16(0xffff, ioaddr + MID_1L + 8 * i); |
| 1004 | iowrite16(0xffff, ioaddr + MID_0M + 8 * i); | 1001 | iowrite16(0xffff, ioaddr + MID_1M + 8 * i); |
| 1005 | iowrite16(0xffff, ioaddr + MID_0H + 8 * i); | 1002 | iowrite16(0xffff, ioaddr + MID_1H + 8 * i); |
| 1006 | } | 1003 | } |
| 1007 | i++; | 1004 | i++; |
| 1008 | } | 1005 | } |
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index a214a1627e8b..4111a85ec80e 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c | |||
| @@ -1686,7 +1686,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
| 1686 | } | 1686 | } |
| 1687 | pr_info("done!\n"); | 1687 | pr_info("done!\n"); |
| 1688 | 1688 | ||
| 1689 | if (!request_mem_region(res->start, (res->end - res->start), | 1689 | if (!request_mem_region(res->start, resource_size(res), |
| 1690 | pdev->name)) { | 1690 | pdev->name)) { |
| 1691 | pr_err("%s: ERROR: memory allocation failed" | 1691 | pr_err("%s: ERROR: memory allocation failed" |
| 1692 | "cannot get the I/O addr 0x%x\n", | 1692 | "cannot get the I/O addr 0x%x\n", |
| @@ -1695,9 +1695,9 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
| 1695 | goto out; | 1695 | goto out; |
| 1696 | } | 1696 | } |
| 1697 | 1697 | ||
| 1698 | addr = ioremap(res->start, (res->end - res->start)); | 1698 | addr = ioremap(res->start, resource_size(res)); |
| 1699 | if (!addr) { | 1699 | if (!addr) { |
| 1700 | pr_err("%s: ERROR: memory mapping failed \n", __func__); | 1700 | pr_err("%s: ERROR: memory mapping failed\n", __func__); |
| 1701 | ret = -ENOMEM; | 1701 | ret = -ENOMEM; |
| 1702 | goto out; | 1702 | goto out; |
| 1703 | } | 1703 | } |
| @@ -1775,7 +1775,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
| 1775 | out: | 1775 | out: |
| 1776 | if (ret < 0) { | 1776 | if (ret < 0) { |
| 1777 | platform_set_drvdata(pdev, NULL); | 1777 | platform_set_drvdata(pdev, NULL); |
| 1778 | release_mem_region(res->start, (res->end - res->start)); | 1778 | release_mem_region(res->start, resource_size(res)); |
| 1779 | if (addr != NULL) | 1779 | if (addr != NULL) |
| 1780 | iounmap(addr); | 1780 | iounmap(addr); |
| 1781 | } | 1781 | } |
| @@ -1813,7 +1813,7 @@ static int stmmac_dvr_remove(struct platform_device *pdev) | |||
| 1813 | 1813 | ||
| 1814 | iounmap((void *)ndev->base_addr); | 1814 | iounmap((void *)ndev->base_addr); |
| 1815 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1815 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1816 | release_mem_region(res->start, (res->end - res->start)); | 1816 | release_mem_region(res->start, resource_size(res)); |
| 1817 | 1817 | ||
| 1818 | free_netdev(ndev); | 1818 | free_netdev(ndev); |
| 1819 | 1819 | ||
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 6fb783ce20b9..b0577dd1a42d 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -327,6 +327,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp) | |||
| 327 | struct scatterlist sg[2]; | 327 | struct scatterlist sg[2]; |
| 328 | int err; | 328 | int err; |
| 329 | 329 | ||
| 330 | sg_init_table(sg, 2); | ||
| 330 | skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN); | 331 | skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN); |
| 331 | if (unlikely(!skb)) | 332 | if (unlikely(!skb)) |
| 332 | return -ENOMEM; | 333 | return -ENOMEM; |
| @@ -352,6 +353,7 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) | |||
| 352 | char *p; | 353 | char *p; |
| 353 | int i, err, offset; | 354 | int i, err, offset; |
| 354 | 355 | ||
| 356 | sg_init_table(sg, MAX_SKB_FRAGS + 2); | ||
| 355 | /* page in sg[MAX_SKB_FRAGS + 1] is list tail */ | 357 | /* page in sg[MAX_SKB_FRAGS + 1] is list tail */ |
| 356 | for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { | 358 | for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { |
| 357 | first = get_a_page(vi, gfp); | 359 | first = get_a_page(vi, gfp); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 67ca4e5a6017..115e1aeedb59 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -1532,8 +1532,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
| 1532 | all_wiphys_idle = ath9k_all_wiphys_idle(sc); | 1532 | all_wiphys_idle = ath9k_all_wiphys_idle(sc); |
| 1533 | ath9k_set_wiphy_idle(aphy, idle); | 1533 | ath9k_set_wiphy_idle(aphy, idle); |
| 1534 | 1534 | ||
| 1535 | if (!idle && all_wiphys_idle) | 1535 | enable_radio = (!idle && all_wiphys_idle); |
| 1536 | enable_radio = true; | ||
| 1537 | 1536 | ||
| 1538 | /* | 1537 | /* |
| 1539 | * After we unlock here its possible another wiphy | 1538 | * After we unlock here its possible another wiphy |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 83c52a682622..8972166386cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
| @@ -2015,7 +2015,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
| 2015 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " | 2015 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " |
| 2016 | "%d index %d\n", scd_ssn , index); | 2016 | "%d index %d\n", scd_ssn , index); |
| 2017 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2017 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); |
| 2018 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | 2018 | if (qc) |
| 2019 | iwl_free_tfds_in_queue(priv, sta_id, | ||
| 2020 | tid, freed); | ||
| 2019 | 2021 | ||
| 2020 | if (priv->mac80211_registered && | 2022 | if (priv->mac80211_registered && |
| 2021 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | 2023 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && |
| @@ -2041,14 +2043,17 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
| 2041 | tx_resp->failure_frame); | 2043 | tx_resp->failure_frame); |
| 2042 | 2044 | ||
| 2043 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2045 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); |
| 2044 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | 2046 | if (qc && likely(sta_id != IWL_INVALID_STATION)) |
| 2047 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
| 2048 | else if (sta_id == IWL_INVALID_STATION) | ||
| 2049 | IWL_DEBUG_TX_REPLY(priv, "Station not known\n"); | ||
| 2045 | 2050 | ||
| 2046 | if (priv->mac80211_registered && | 2051 | if (priv->mac80211_registered && |
| 2047 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | 2052 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) |
| 2048 | iwl_wake_queue(priv, txq_id); | 2053 | iwl_wake_queue(priv, txq_id); |
| 2049 | } | 2054 | } |
| 2050 | 2055 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | |
| 2051 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | 2056 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); |
| 2052 | 2057 | ||
| 2053 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | 2058 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) |
| 2054 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); | 2059 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 35f819ac87a3..1460116d329f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
| @@ -346,6 +346,17 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | |||
| 346 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); | 346 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | /* | ||
| 350 | * Static function to get the expected throughput from an iwl_scale_tbl_info | ||
| 351 | * that wraps a NULL pointer check | ||
| 352 | */ | ||
| 353 | static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) | ||
| 354 | { | ||
| 355 | if (tbl->expected_tpt) | ||
| 356 | return tbl->expected_tpt[rs_index]; | ||
| 357 | return 0; | ||
| 358 | } | ||
| 359 | |||
| 349 | /** | 360 | /** |
| 350 | * rs_collect_tx_data - Update the success/failure sliding window | 361 | * rs_collect_tx_data - Update the success/failure sliding window |
| 351 | * | 362 | * |
| @@ -353,19 +364,21 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | |||
| 353 | * at this rate. window->data contains the bitmask of successful | 364 | * at this rate. window->data contains the bitmask of successful |
| 354 | * packets. | 365 | * packets. |
| 355 | */ | 366 | */ |
| 356 | static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | 367 | static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, |
| 357 | int scale_index, s32 tpt, int attempts, | 368 | int scale_index, int attempts, int successes) |
| 358 | int successes) | ||
| 359 | { | 369 | { |
| 360 | struct iwl_rate_scale_data *window = NULL; | 370 | struct iwl_rate_scale_data *window = NULL; |
| 361 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); | 371 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); |
| 362 | s32 fail_count; | 372 | s32 fail_count, tpt; |
| 363 | 373 | ||
| 364 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | 374 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) |
| 365 | return -EINVAL; | 375 | return -EINVAL; |
| 366 | 376 | ||
| 367 | /* Select window for current tx bit rate */ | 377 | /* Select window for current tx bit rate */ |
| 368 | window = &(windows[scale_index]); | 378 | window = &(tbl->win[scale_index]); |
| 379 | |||
| 380 | /* Get expected throughput */ | ||
| 381 | tpt = get_expected_tpt(tbl, scale_index); | ||
| 369 | 382 | ||
| 370 | /* | 383 | /* |
| 371 | * Keep track of only the latest 62 tx frame attempts in this rate's | 384 | * 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, | |||
| 739 | return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && | 752 | return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && |
| 740 | (a->is_SGI == b->is_SGI); | 753 | (a->is_SGI == b->is_SGI); |
| 741 | } | 754 | } |
| 742 | /* | ||
| 743 | * Static function to get the expected throughput from an iwl_scale_tbl_info | ||
| 744 | * that wraps a NULL pointer check | ||
| 745 | */ | ||
| 746 | static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) | ||
| 747 | { | ||
| 748 | if (tbl->expected_tpt) | ||
| 749 | return tbl->expected_tpt[rs_index]; | ||
| 750 | return 0; | ||
| 751 | } | ||
| 752 | 755 | ||
| 753 | /* | 756 | /* |
| 754 | * mac80211 sends us Tx status | 757 | * mac80211 sends us Tx status |
| @@ -765,12 +768,10 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
| 765 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 768 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 766 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 769 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
| 767 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 770 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 768 | struct iwl_rate_scale_data *window = NULL; | ||
| 769 | enum mac80211_rate_control_flags mac_flags; | 771 | enum mac80211_rate_control_flags mac_flags; |
| 770 | u32 tx_rate; | 772 | u32 tx_rate; |
| 771 | struct iwl_scale_tbl_info tbl_type; | 773 | struct iwl_scale_tbl_info tbl_type; |
| 772 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl; | 774 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
| 773 | s32 tpt = 0; | ||
| 774 | 775 | ||
| 775 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 776 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); |
| 776 | 777 | ||
| @@ -853,7 +854,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
| 853 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); | 854 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); |
| 854 | return; | 855 | return; |
| 855 | } | 856 | } |
| 856 | window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); | ||
| 857 | 857 | ||
| 858 | /* | 858 | /* |
| 859 | * Updating the frame history depends on whether packets were | 859 | * 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, | |||
| 866 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); | 866 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); |
| 867 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, | 867 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, |
| 868 | &rs_index); | 868 | &rs_index); |
| 869 | tpt = get_expected_tpt(curr_tbl, rs_index); | 869 | rs_collect_tx_data(curr_tbl, rs_index, |
| 870 | rs_collect_tx_data(window, rs_index, tpt, | ||
| 871 | info->status.ampdu_ack_len, | 870 | info->status.ampdu_ack_len, |
| 872 | info->status.ampdu_ack_map); | 871 | info->status.ampdu_ack_map); |
| 873 | 872 | ||
| @@ -897,19 +896,13 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
| 897 | * table as active/search. | 896 | * table as active/search. |
| 898 | */ | 897 | */ |
| 899 | if (table_type_matches(&tbl_type, curr_tbl)) | 898 | if (table_type_matches(&tbl_type, curr_tbl)) |
| 900 | tpt = get_expected_tpt(curr_tbl, rs_index); | 899 | tmp_tbl = curr_tbl; |
| 901 | else if (table_type_matches(&tbl_type, other_tbl)) | 900 | else if (table_type_matches(&tbl_type, other_tbl)) |
| 902 | tpt = get_expected_tpt(other_tbl, rs_index); | 901 | tmp_tbl = other_tbl; |
| 903 | else | 902 | else |
| 904 | continue; | 903 | continue; |
| 905 | 904 | rs_collect_tx_data(tmp_tbl, rs_index, 1, | |
| 906 | /* Constants mean 1 transmission, 0 successes */ | 905 | i < retries ? 0 : legacy_success); |
| 907 | if (i < retries) | ||
| 908 | rs_collect_tx_data(window, rs_index, tpt, 1, | ||
| 909 | 0); | ||
| 910 | else | ||
| 911 | rs_collect_tx_data(window, rs_index, tpt, 1, | ||
| 912 | legacy_success); | ||
| 913 | } | 906 | } |
| 914 | 907 | ||
| 915 | /* Update success/fail counts if not searching for new mode */ | 908 | /* Update success/fail counts if not searching for new mode */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index db050b811232..3352f7086632 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
| @@ -308,10 +308,13 @@ int iwl_hw_nic_init(struct iwl_priv *priv) | |||
| 308 | 308 | ||
| 309 | spin_unlock_irqrestore(&priv->lock, flags); | 309 | spin_unlock_irqrestore(&priv->lock, flags); |
| 310 | 310 | ||
| 311 | /* Allocate and init all Tx and Command queues */ | 311 | /* Allocate or reset and init all Tx and Command queues */ |
| 312 | ret = iwl_txq_ctx_reset(priv); | 312 | if (!priv->txq) { |
| 313 | if (ret) | 313 | ret = iwl_txq_ctx_alloc(priv); |
| 314 | return ret; | 314 | if (ret) |
| 315 | return ret; | ||
| 316 | } else | ||
| 317 | iwl_txq_ctx_reset(priv); | ||
| 315 | 318 | ||
| 316 | set_bit(STATUS_INIT, &priv->status); | 319 | set_bit(STATUS_INIT, &priv->status); |
| 317 | 320 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4ef7739f9e8e..732590f5fe30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
| @@ -442,7 +442,8 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | |||
| 442 | /***************************************************** | 442 | /***************************************************** |
| 443 | * TX | 443 | * TX |
| 444 | ******************************************************/ | 444 | ******************************************************/ |
| 445 | int iwl_txq_ctx_reset(struct iwl_priv *priv); | 445 | int iwl_txq_ctx_alloc(struct iwl_priv *priv); |
| 446 | void iwl_txq_ctx_reset(struct iwl_priv *priv); | ||
| 446 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 447 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
| 447 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | 448 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, |
| 448 | struct iwl_tx_queue *txq, | 449 | struct iwl_tx_queue *txq, |
| @@ -456,6 +457,8 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv, | |||
| 456 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 457 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
| 457 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 458 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
| 458 | int slots_num, u32 txq_id); | 459 | int slots_num, u32 txq_id); |
| 460 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
| 461 | int slots_num, u32 txq_id); | ||
| 459 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 462 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
| 460 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); | 463 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); |
| 461 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | 464 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index f0b7e6cfbe4f..8dd0c036d547 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
| @@ -194,10 +194,34 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
| 194 | struct iwl_queue *q = &txq->q; | 194 | struct iwl_queue *q = &txq->q; |
| 195 | struct device *dev = &priv->pci_dev->dev; | 195 | struct device *dev = &priv->pci_dev->dev; |
| 196 | int i; | 196 | int i; |
| 197 | bool huge = false; | ||
| 197 | 198 | ||
| 198 | if (q->n_bd == 0) | 199 | if (q->n_bd == 0) |
| 199 | return; | 200 | return; |
| 200 | 201 | ||
| 202 | for (; q->read_ptr != q->write_ptr; | ||
| 203 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
| 204 | /* we have no way to tell if it is a huge cmd ATM */ | ||
| 205 | i = get_cmd_index(q, q->read_ptr, 0); | ||
| 206 | |||
| 207 | if (txq->meta[i].flags & CMD_SIZE_HUGE) { | ||
| 208 | huge = true; | ||
| 209 | continue; | ||
| 210 | } | ||
| 211 | |||
| 212 | pci_unmap_single(priv->pci_dev, | ||
| 213 | pci_unmap_addr(&txq->meta[i], mapping), | ||
| 214 | pci_unmap_len(&txq->meta[i], len), | ||
| 215 | PCI_DMA_BIDIRECTIONAL); | ||
| 216 | } | ||
| 217 | if (huge) { | ||
| 218 | i = q->n_window; | ||
| 219 | pci_unmap_single(priv->pci_dev, | ||
| 220 | pci_unmap_addr(&txq->meta[i], mapping), | ||
| 221 | pci_unmap_len(&txq->meta[i], len), | ||
| 222 | PCI_DMA_BIDIRECTIONAL); | ||
| 223 | } | ||
| 224 | |||
| 201 | /* De-alloc array of command/tx buffers */ | 225 | /* De-alloc array of command/tx buffers */ |
| 202 | for (i = 0; i <= TFD_CMD_SLOTS; i++) | 226 | for (i = 0; i <= TFD_CMD_SLOTS; i++) |
| 203 | kfree(txq->cmd[i]); | 227 | kfree(txq->cmd[i]); |
| @@ -410,6 +434,26 @@ out_free_arrays: | |||
| 410 | } | 434 | } |
| 411 | EXPORT_SYMBOL(iwl_tx_queue_init); | 435 | EXPORT_SYMBOL(iwl_tx_queue_init); |
| 412 | 436 | ||
| 437 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
| 438 | int slots_num, u32 txq_id) | ||
| 439 | { | ||
| 440 | int actual_slots = slots_num; | ||
| 441 | |||
| 442 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
| 443 | actual_slots++; | ||
| 444 | |||
| 445 | memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); | ||
| 446 | |||
| 447 | txq->need_update = 0; | ||
| 448 | |||
| 449 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | ||
| 450 | iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | ||
| 451 | |||
| 452 | /* Tell device where to find queue */ | ||
| 453 | priv->cfg->ops->lib->txq_init(priv, txq); | ||
| 454 | } | ||
| 455 | EXPORT_SYMBOL(iwl_tx_queue_reset); | ||
| 456 | |||
| 413 | /** | 457 | /** |
| 414 | * iwl_hw_txq_ctx_free - Free TXQ Context | 458 | * iwl_hw_txq_ctx_free - Free TXQ Context |
| 415 | * | 459 | * |
| @@ -421,8 +465,7 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | |||
| 421 | 465 | ||
| 422 | /* Tx queues */ | 466 | /* Tx queues */ |
| 423 | if (priv->txq) { | 467 | if (priv->txq) { |
| 424 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; | 468 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) |
| 425 | txq_id++) | ||
| 426 | if (txq_id == IWL_CMD_QUEUE_NUM) | 469 | if (txq_id == IWL_CMD_QUEUE_NUM) |
| 427 | iwl_cmd_queue_free(priv); | 470 | iwl_cmd_queue_free(priv); |
| 428 | else | 471 | else |
| @@ -438,15 +481,15 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | |||
| 438 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | 481 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); |
| 439 | 482 | ||
| 440 | /** | 483 | /** |
| 441 | * iwl_txq_ctx_reset - Reset TX queue context | 484 | * iwl_txq_ctx_alloc - allocate TX queue context |
| 442 | * Destroys all DMA structures and initialize them again | 485 | * Allocate all Tx DMA structures and initialize them |
| 443 | * | 486 | * |
| 444 | * @param priv | 487 | * @param priv |
| 445 | * @return error code | 488 | * @return error code |
| 446 | */ | 489 | */ |
| 447 | int iwl_txq_ctx_reset(struct iwl_priv *priv) | 490 | int iwl_txq_ctx_alloc(struct iwl_priv *priv) |
| 448 | { | 491 | { |
| 449 | int ret = 0; | 492 | int ret; |
| 450 | int txq_id, slots_num; | 493 | int txq_id, slots_num; |
| 451 | unsigned long flags; | 494 | unsigned long flags; |
| 452 | 495 | ||
| @@ -504,8 +547,31 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
| 504 | return ret; | 547 | return ret; |
| 505 | } | 548 | } |
| 506 | 549 | ||
| 550 | void iwl_txq_ctx_reset(struct iwl_priv *priv) | ||
| 551 | { | ||
| 552 | int txq_id, slots_num; | ||
| 553 | unsigned long flags; | ||
| 554 | |||
| 555 | spin_lock_irqsave(&priv->lock, flags); | ||
| 556 | |||
| 557 | /* Turn off all Tx DMA fifos */ | ||
| 558 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
| 559 | |||
| 560 | /* Tell NIC where to find the "keep warm" buffer */ | ||
| 561 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
| 562 | |||
| 563 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 564 | |||
| 565 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
| 566 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
| 567 | slots_num = txq_id == IWL_CMD_QUEUE_NUM ? | ||
| 568 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
| 569 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 507 | /** | 573 | /** |
| 508 | * iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory | 574 | * iwl_txq_ctx_stop - Stop all Tx DMA channels |
| 509 | */ | 575 | */ |
| 510 | void iwl_txq_ctx_stop(struct iwl_priv *priv) | 576 | void iwl_txq_ctx_stop(struct iwl_priv *priv) |
| 511 | { | 577 | { |
| @@ -525,9 +591,6 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv) | |||
| 525 | 1000); | 591 | 1000); |
| 526 | } | 592 | } |
| 527 | spin_unlock_irqrestore(&priv->lock, flags); | 593 | spin_unlock_irqrestore(&priv->lock, flags); |
| 528 | |||
| 529 | /* Deallocate memory for all Tx queues */ | ||
| 530 | iwl_hw_txq_ctx_free(priv); | ||
| 531 | } | 594 | } |
| 532 | EXPORT_SYMBOL(iwl_txq_ctx_stop); | 595 | EXPORT_SYMBOL(iwl_txq_ctx_stop); |
| 533 | 596 | ||
| @@ -1050,6 +1113,14 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
| 1050 | 1113 | ||
| 1051 | spin_lock_irqsave(&priv->hcmd_lock, flags); | 1114 | spin_lock_irqsave(&priv->hcmd_lock, flags); |
| 1052 | 1115 | ||
| 1116 | /* If this is a huge cmd, mark the huge flag also on the meta.flags | ||
| 1117 | * of the _original_ cmd. This is used for DMA mapping clean up. | ||
| 1118 | */ | ||
| 1119 | if (cmd->flags & CMD_SIZE_HUGE) { | ||
| 1120 | idx = get_cmd_index(q, q->write_ptr, 0); | ||
| 1121 | txq->meta[idx].flags = CMD_SIZE_HUGE; | ||
| 1122 | } | ||
| 1123 | |||
| 1053 | idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); | 1124 | idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); |
| 1054 | out_cmd = txq->cmd[idx]; | 1125 | out_cmd = txq->cmd[idx]; |
| 1055 | out_meta = &txq->meta[idx]; | 1126 | out_meta = &txq->meta[idx]; |
| @@ -1227,6 +1298,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
| 1227 | bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); | 1298 | bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); |
| 1228 | struct iwl_device_cmd *cmd; | 1299 | struct iwl_device_cmd *cmd; |
| 1229 | struct iwl_cmd_meta *meta; | 1300 | struct iwl_cmd_meta *meta; |
| 1301 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; | ||
| 1230 | 1302 | ||
| 1231 | /* If a Tx command is being handled and it isn't in the actual | 1303 | /* If a Tx command is being handled and it isn't in the actual |
| 1232 | * command queue then there a command routing bug has been introduced | 1304 | * 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) | |||
| 1240 | return; | 1312 | return; |
| 1241 | } | 1313 | } |
| 1242 | 1314 | ||
| 1243 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); | 1315 | /* If this is a huge cmd, clear the huge flag on the meta.flags |
| 1244 | cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; | 1316 | * of the _original_ cmd. So that iwl_cmd_queue_free won't unmap |
| 1245 | meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index]; | 1317 | * the DMA buffer for the scan (huge) command. |
| 1318 | */ | ||
| 1319 | if (huge) { | ||
| 1320 | cmd_index = get_cmd_index(&txq->q, index, 0); | ||
| 1321 | txq->meta[cmd_index].flags = 0; | ||
| 1322 | } | ||
| 1323 | cmd_index = get_cmd_index(&txq->q, index, huge); | ||
| 1324 | cmd = txq->cmd[cmd_index]; | ||
| 1325 | meta = &txq->meta[cmd_index]; | ||
| 1246 | 1326 | ||
| 1247 | pci_unmap_single(priv->pci_dev, | 1327 | pci_unmap_single(priv->pci_dev, |
| 1248 | pci_unmap_addr(meta, mapping), | 1328 | pci_unmap_addr(meta, mapping), |
| @@ -1264,6 +1344,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
| 1264 | get_cmd_string(cmd->hdr.cmd)); | 1344 | get_cmd_string(cmd->hdr.cmd)); |
| 1265 | wake_up_interruptible(&priv->wait_command_queue); | 1345 | wake_up_interruptible(&priv->wait_command_queue); |
| 1266 | } | 1346 | } |
| 1347 | meta->flags = 0; | ||
| 1267 | } | 1348 | } |
| 1268 | EXPORT_SYMBOL(iwl_tx_cmd_complete); | 1349 | EXPORT_SYMBOL(iwl_tx_cmd_complete); |
| 1269 | 1350 | ||
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 5be11c99e18f..e69d238c5af0 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
| @@ -236,6 +236,10 @@ static int vq_memory_access_ok(void __user *log_base, struct vhost_memory *mem, | |||
| 236 | int log_all) | 236 | int log_all) |
| 237 | { | 237 | { |
| 238 | int i; | 238 | int i; |
| 239 | |||
| 240 | if (!mem) | ||
| 241 | return 0; | ||
| 242 | |||
| 239 | for (i = 0; i < mem->nregions; ++i) { | 243 | for (i = 0; i < mem->nregions; ++i) { |
| 240 | struct vhost_memory_region *m = mem->regions + i; | 244 | struct vhost_memory_region *m = mem->regions + i; |
| 241 | unsigned long a = m->userspace_addr; | 245 | unsigned long a = m->userspace_addr; |
diff --git a/include/net/x25.h b/include/net/x25.h index 15ef9624ab75..468551ea4f1d 100644 --- a/include/net/x25.h +++ b/include/net/x25.h | |||
| @@ -183,6 +183,10 @@ extern int sysctl_x25_clear_request_timeout; | |||
| 183 | extern int sysctl_x25_ack_holdback_timeout; | 183 | extern int sysctl_x25_ack_holdback_timeout; |
| 184 | extern int sysctl_x25_forward; | 184 | extern int sysctl_x25_forward; |
| 185 | 185 | ||
| 186 | extern int x25_parse_address_block(struct sk_buff *skb, | ||
| 187 | struct x25_address *called_addr, | ||
| 188 | struct x25_address *calling_addr); | ||
| 189 | |||
| 186 | extern int x25_addr_ntoa(unsigned char *, struct x25_address *, | 190 | extern int x25_addr_ntoa(unsigned char *, struct x25_address *, |
| 187 | struct x25_address *); | 191 | struct x25_address *); |
| 188 | extern int x25_addr_aton(unsigned char *, struct x25_address *, | 192 | extern int x25_addr_aton(unsigned char *, struct x25_address *, |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 6980625537ca..f29ada827a6a 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -723,7 +723,7 @@ static int br_multicast_igmp3_report(struct net_bridge *br, | |||
| 723 | if (!pskb_may_pull(skb, len)) | 723 | if (!pskb_may_pull(skb, len)) |
| 724 | return -EINVAL; | 724 | return -EINVAL; |
| 725 | 725 | ||
| 726 | grec = (void *)(skb->data + len); | 726 | grec = (void *)(skb->data + len - sizeof(*grec)); |
| 727 | group = grec->grec_mca; | 727 | group = grec->grec_mca; |
| 728 | type = grec->grec_type; | 728 | type = grec->grec_type; |
| 729 | 729 | ||
diff --git a/net/can/raw.c b/net/can/raw.c index 3a7dffb6519c..da99cf153b33 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
| @@ -445,7 +445,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, | |||
| 445 | return -EFAULT; | 445 | return -EFAULT; |
| 446 | } | 446 | } |
| 447 | } else if (count == 1) { | 447 | } else if (count == 1) { |
| 448 | if (copy_from_user(&sfilter, optval, optlen)) | 448 | if (copy_from_user(&sfilter, optval, sizeof(sfilter))) |
| 449 | return -EFAULT; | 449 | return -EFAULT; |
| 450 | } | 450 | } |
| 451 | 451 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 954bbfb39dff..8fef859db35d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -472,8 +472,8 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
| 472 | if (hslot->count < hslot2->count) | 472 | if (hslot->count < hslot2->count) |
| 473 | goto begin; | 473 | goto begin; |
| 474 | 474 | ||
| 475 | result = udp4_lib_lookup2(net, INADDR_ANY, sport, | 475 | result = udp4_lib_lookup2(net, saddr, sport, |
| 476 | daddr, hnum, dif, | 476 | INADDR_ANY, hnum, dif, |
| 477 | hslot2, slot2); | 477 | hslot2, slot2); |
| 478 | } | 478 | } |
| 479 | rcu_read_unlock(); | 479 | rcu_read_unlock(); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index c177aea88c0b..90824852f598 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -259,8 +259,8 @@ static struct sock *__udp6_lib_lookup(struct net *net, | |||
| 259 | if (hslot->count < hslot2->count) | 259 | if (hslot->count < hslot2->count) |
| 260 | goto begin; | 260 | goto begin; |
| 261 | 261 | ||
| 262 | result = udp6_lib_lookup2(net, &in6addr_any, sport, | 262 | result = udp6_lib_lookup2(net, saddr, sport, |
| 263 | daddr, hnum, dif, | 263 | &in6addr_any, hnum, dif, |
| 264 | hslot2, slot2); | 264 | hslot2, slot2); |
| 265 | } | 265 | } |
| 266 | rcu_read_unlock(); | 266 | rcu_read_unlock(); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 06c33b68d8e5..b887e484ae04 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -225,11 +225,11 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
| 225 | switch (sdata->vif.type) { | 225 | switch (sdata->vif.type) { |
| 226 | case NL80211_IFTYPE_AP: | 226 | case NL80211_IFTYPE_AP: |
| 227 | sdata->vif.bss_conf.enable_beacon = | 227 | sdata->vif.bss_conf.enable_beacon = |
| 228 | !!rcu_dereference(sdata->u.ap.beacon); | 228 | !!sdata->u.ap.beacon; |
| 229 | break; | 229 | break; |
| 230 | case NL80211_IFTYPE_ADHOC: | 230 | case NL80211_IFTYPE_ADHOC: |
| 231 | sdata->vif.bss_conf.enable_beacon = | 231 | sdata->vif.bss_conf.enable_beacon = |
| 232 | !!rcu_dereference(sdata->u.ibss.presp); | 232 | !!sdata->u.ibss.presp; |
| 233 | break; | 233 | break; |
| 234 | case NL80211_IFTYPE_MESH_POINT: | 234 | case NL80211_IFTYPE_MESH_POINT: |
| 235 | sdata->vif.bss_conf.enable_beacon = true; | 235 | sdata->vif.bss_conf.enable_beacon = true; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 58e3e3a61d99..859ee5f3d941 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
| @@ -750,9 +750,6 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
| 750 | 750 | ||
| 751 | switch (fc & IEEE80211_FCTL_STYPE) { | 751 | switch (fc & IEEE80211_FCTL_STYPE) { |
| 752 | case IEEE80211_STYPE_ACTION: | 752 | case IEEE80211_STYPE_ACTION: |
| 753 | if (skb->len < IEEE80211_MIN_ACTION_SIZE) | ||
| 754 | return RX_DROP_MONITOR; | ||
| 755 | /* fall through */ | ||
| 756 | case IEEE80211_STYPE_PROBE_RESP: | 753 | case IEEE80211_STYPE_PROBE_RESP: |
| 757 | case IEEE80211_STYPE_BEACON: | 754 | case IEEE80211_STYPE_BEACON: |
| 758 | skb_queue_tail(&ifmsh->skb_queue, skb); | 755 | skb_queue_tail(&ifmsh->skb_queue, skb); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f0accf622cd7..04ea07f0e78a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -1974,6 +1974,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
| 1974 | goto handled; | 1974 | goto handled; |
| 1975 | } | 1975 | } |
| 1976 | break; | 1976 | break; |
| 1977 | case MESH_PLINK_CATEGORY: | ||
| 1978 | case MESH_PATH_SEL_CATEGORY: | ||
| 1979 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
| 1980 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | ||
| 1981 | break; | ||
| 1977 | } | 1982 | } |
| 1978 | 1983 | ||
| 1979 | /* | 1984 | /* |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 56422d894351..fb12cec4d333 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
| @@ -93,12 +93,18 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
| 93 | struct ieee80211_local *local = sdata->local; | 93 | struct ieee80211_local *local = sdata->local; |
| 94 | struct sta_info *sta; | 94 | struct sta_info *sta; |
| 95 | 95 | ||
| 96 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 96 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
| 97 | rcu_read_lock_held() || | ||
| 98 | lockdep_is_held(&local->sta_lock) || | ||
| 99 | lockdep_is_held(&local->sta_mtx)); | ||
| 97 | while (sta) { | 100 | while (sta) { |
| 98 | if (sta->sdata == sdata && | 101 | if (sta->sdata == sdata && |
| 99 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 102 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
| 100 | break; | 103 | break; |
| 101 | sta = rcu_dereference(sta->hnext); | 104 | sta = rcu_dereference_check(sta->hnext, |
| 105 | rcu_read_lock_held() || | ||
| 106 | lockdep_is_held(&local->sta_lock) || | ||
| 107 | lockdep_is_held(&local->sta_mtx)); | ||
| 102 | } | 108 | } |
| 103 | return sta; | 109 | return sta; |
| 104 | } | 110 | } |
| @@ -113,13 +119,19 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
| 113 | struct ieee80211_local *local = sdata->local; | 119 | struct ieee80211_local *local = sdata->local; |
| 114 | struct sta_info *sta; | 120 | struct sta_info *sta; |
| 115 | 121 | ||
| 116 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 122 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
| 123 | rcu_read_lock_held() || | ||
| 124 | lockdep_is_held(&local->sta_lock) || | ||
| 125 | lockdep_is_held(&local->sta_mtx)); | ||
| 117 | while (sta) { | 126 | while (sta) { |
| 118 | if ((sta->sdata == sdata || | 127 | if ((sta->sdata == sdata || |
| 119 | sta->sdata->bss == sdata->bss) && | 128 | sta->sdata->bss == sdata->bss) && |
| 120 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 129 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
| 121 | break; | 130 | break; |
| 122 | sta = rcu_dereference(sta->hnext); | 131 | sta = rcu_dereference_check(sta->hnext, |
| 132 | rcu_read_lock_held() || | ||
| 133 | lockdep_is_held(&local->sta_lock) || | ||
| 134 | lockdep_is_held(&local->sta_mtx)); | ||
| 123 | } | 135 | } |
| 124 | return sta; | 136 | return sta; |
| 125 | } | 137 | } |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index e56f711baccc..cbddd0cb83f1 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
| @@ -83,6 +83,41 @@ struct compat_x25_subscrip_struct { | |||
| 83 | }; | 83 | }; |
| 84 | #endif | 84 | #endif |
| 85 | 85 | ||
| 86 | |||
| 87 | int x25_parse_address_block(struct sk_buff *skb, | ||
| 88 | struct x25_address *called_addr, | ||
| 89 | struct x25_address *calling_addr) | ||
| 90 | { | ||
| 91 | unsigned char len; | ||
| 92 | int needed; | ||
| 93 | int rc; | ||
| 94 | |||
| 95 | if (skb->len < 1) { | ||
| 96 | /* packet has no address block */ | ||
| 97 | rc = 0; | ||
| 98 | goto empty; | ||
| 99 | } | ||
| 100 | |||
| 101 | len = *skb->data; | ||
| 102 | needed = 1 + (len >> 4) + (len & 0x0f); | ||
| 103 | |||
| 104 | if (skb->len < needed) { | ||
| 105 | /* packet is too short to hold the addresses it claims | ||
| 106 | to hold */ | ||
| 107 | rc = -1; | ||
| 108 | goto empty; | ||
| 109 | } | ||
| 110 | |||
| 111 | return x25_addr_ntoa(skb->data, called_addr, calling_addr); | ||
| 112 | |||
| 113 | empty: | ||
| 114 | *called_addr->x25_addr = 0; | ||
| 115 | *calling_addr->x25_addr = 0; | ||
| 116 | |||
| 117 | return rc; | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 86 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, | 121 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, |
| 87 | struct x25_address *calling_addr) | 122 | struct x25_address *calling_addr) |
| 88 | { | 123 | { |
| @@ -554,7 +589,8 @@ static int x25_create(struct net *net, struct socket *sock, int protocol, | |||
| 554 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; | 589 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; |
| 555 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; | 590 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; |
| 556 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; | 591 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; |
| 557 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; | 592 | x25->facilities.throughput = 0; /* by default don't negotiate |
| 593 | throughput */ | ||
| 558 | x25->facilities.reverse = X25_DEFAULT_REVERSE; | 594 | x25->facilities.reverse = X25_DEFAULT_REVERSE; |
| 559 | x25->dte_facilities.calling_len = 0; | 595 | x25->dte_facilities.calling_len = 0; |
| 560 | x25->dte_facilities.called_len = 0; | 596 | x25->dte_facilities.called_len = 0; |
| @@ -922,16 +958,26 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
| 922 | /* | 958 | /* |
| 923 | * Extract the X.25 addresses and convert them to ASCII strings, | 959 | * Extract the X.25 addresses and convert them to ASCII strings, |
| 924 | * and remove them. | 960 | * and remove them. |
| 961 | * | ||
| 962 | * Address block is mandatory in call request packets | ||
| 925 | */ | 963 | */ |
| 926 | addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr); | 964 | addr_len = x25_parse_address_block(skb, &source_addr, &dest_addr); |
| 965 | if (addr_len <= 0) | ||
| 966 | goto out_clear_request; | ||
| 927 | skb_pull(skb, addr_len); | 967 | skb_pull(skb, addr_len); |
| 928 | 968 | ||
| 929 | /* | 969 | /* |
| 930 | * Get the length of the facilities, skip past them for the moment | 970 | * Get the length of the facilities, skip past them for the moment |
| 931 | * get the call user data because this is needed to determine | 971 | * get the call user data because this is needed to determine |
| 932 | * the correct listener | 972 | * the correct listener |
| 973 | * | ||
| 974 | * Facilities length is mandatory in call request packets | ||
| 933 | */ | 975 | */ |
| 976 | if (skb->len < 1) | ||
| 977 | goto out_clear_request; | ||
| 934 | len = skb->data[0] + 1; | 978 | len = skb->data[0] + 1; |
| 979 | if (skb->len < len) | ||
| 980 | goto out_clear_request; | ||
| 935 | skb_pull(skb,len); | 981 | skb_pull(skb,len); |
| 936 | 982 | ||
| 937 | /* | 983 | /* |
| @@ -1415,9 +1461,20 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 1415 | if (facilities.winsize_in < 1 || | 1461 | if (facilities.winsize_in < 1 || |
| 1416 | facilities.winsize_in > 127) | 1462 | facilities.winsize_in > 127) |
| 1417 | break; | 1463 | break; |
| 1418 | if (facilities.throughput < 0x03 || | 1464 | if (facilities.throughput) { |
| 1419 | facilities.throughput > 0xDD) | 1465 | int out = facilities.throughput & 0xf0; |
| 1420 | break; | 1466 | int in = facilities.throughput & 0x0f; |
| 1467 | if (!out) | ||
| 1468 | facilities.throughput |= | ||
| 1469 | X25_DEFAULT_THROUGHPUT << 4; | ||
| 1470 | else if (out < 0x30 || out > 0xD0) | ||
| 1471 | break; | ||
| 1472 | if (!in) | ||
| 1473 | facilities.throughput |= | ||
| 1474 | X25_DEFAULT_THROUGHPUT; | ||
| 1475 | else if (in < 0x03 || in > 0x0D) | ||
| 1476 | break; | ||
| 1477 | } | ||
| 1421 | if (facilities.reverse && | 1478 | if (facilities.reverse && |
| 1422 | (facilities.reverse & 0x81) != 0x81) | 1479 | (facilities.reverse & 0x81) != 0x81) |
| 1423 | break; | 1480 | break; |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index a21f6646eb3a..771bab00754b 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
| @@ -35,7 +35,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
| 35 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) | 35 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) |
| 36 | { | 36 | { |
| 37 | unsigned char *p = skb->data; | 37 | unsigned char *p = skb->data; |
| 38 | unsigned int len = *p++; | 38 | unsigned int len; |
| 39 | 39 | ||
| 40 | *vc_fac_mask = 0; | 40 | *vc_fac_mask = 0; |
| 41 | 41 | ||
| @@ -50,6 +50,14 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
| 50 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); | 50 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); |
| 51 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); | 51 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); |
| 52 | 52 | ||
| 53 | if (skb->len < 1) | ||
| 54 | return 0; | ||
| 55 | |||
| 56 | len = *p++; | ||
| 57 | |||
| 58 | if (len >= skb->len) | ||
| 59 | return -1; | ||
| 60 | |||
| 53 | while (len > 0) { | 61 | while (len > 0) { |
| 54 | switch (*p & X25_FAC_CLASS_MASK) { | 62 | switch (*p & X25_FAC_CLASS_MASK) { |
| 55 | case X25_FAC_CLASS_A: | 63 | case X25_FAC_CLASS_A: |
| @@ -247,6 +255,8 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | |||
| 247 | memcpy(new, ours, sizeof(*new)); | 255 | memcpy(new, ours, sizeof(*new)); |
| 248 | 256 | ||
| 249 | len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); | 257 | len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); |
| 258 | if (len < 0) | ||
| 259 | return len; | ||
| 250 | 260 | ||
| 251 | /* | 261 | /* |
| 252 | * They want reverse charging, we won't accept it. | 262 | * They want reverse charging, we won't accept it. |
| @@ -259,9 +269,18 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | |||
| 259 | new->reverse = theirs.reverse; | 269 | new->reverse = theirs.reverse; |
| 260 | 270 | ||
| 261 | if (theirs.throughput) { | 271 | if (theirs.throughput) { |
| 262 | if (theirs.throughput < ours->throughput) { | 272 | int theirs_in = theirs.throughput & 0x0f; |
| 263 | SOCK_DEBUG(sk, "X.25: throughput negotiated down\n"); | 273 | int theirs_out = theirs.throughput & 0xf0; |
| 264 | new->throughput = theirs.throughput; | 274 | int ours_in = ours->throughput & 0x0f; |
| 275 | int ours_out = ours->throughput & 0xf0; | ||
| 276 | if (!ours_in || theirs_in < ours_in) { | ||
| 277 | SOCK_DEBUG(sk, "X.25: inbound throughput negotiated\n"); | ||
| 278 | new->throughput = (new->throughput & 0xf0) | theirs_in; | ||
| 279 | } | ||
| 280 | if (!ours_out || theirs_out < ours_out) { | ||
| 281 | SOCK_DEBUG(sk, | ||
| 282 | "X.25: outbound throughput negotiated\n"); | ||
| 283 | new->throughput = (new->throughput & 0x0f) | theirs_out; | ||
| 265 | } | 284 | } |
| 266 | } | 285 | } |
| 267 | 286 | ||
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index a31b3b9e5966..372ac226e648 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
| @@ -90,6 +90,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) | |||
| 90 | static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) | 90 | static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) |
| 91 | { | 91 | { |
| 92 | struct x25_address source_addr, dest_addr; | 92 | struct x25_address source_addr, dest_addr; |
| 93 | int len; | ||
| 93 | 94 | ||
| 94 | switch (frametype) { | 95 | switch (frametype) { |
| 95 | case X25_CALL_ACCEPTED: { | 96 | case X25_CALL_ACCEPTED: { |
| @@ -107,11 +108,17 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 107 | * Parse the data in the frame. | 108 | * Parse the data in the frame. |
| 108 | */ | 109 | */ |
| 109 | skb_pull(skb, X25_STD_MIN_LEN); | 110 | skb_pull(skb, X25_STD_MIN_LEN); |
| 110 | skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); | 111 | |
| 111 | skb_pull(skb, | 112 | len = x25_parse_address_block(skb, &source_addr, |
| 112 | x25_parse_facilities(skb, &x25->facilities, | 113 | &dest_addr); |
| 114 | if (len > 0) | ||
| 115 | skb_pull(skb, len); | ||
| 116 | |||
| 117 | len = x25_parse_facilities(skb, &x25->facilities, | ||
| 113 | &x25->dte_facilities, | 118 | &x25->dte_facilities, |
| 114 | &x25->vc_facil_mask)); | 119 | &x25->vc_facil_mask); |
| 120 | if (len > 0) | ||
| 121 | skb_pull(skb, len); | ||
| 115 | /* | 122 | /* |
| 116 | * Copy any Call User Data. | 123 | * Copy any Call User Data. |
| 117 | */ | 124 | */ |
