diff options
46 files changed, 357 insertions, 221 deletions
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt index ab1e8d7004c5..5cb9a1972460 100644 --- a/Documentation/networking/stmmac.txt +++ b/Documentation/networking/stmmac.txt | |||
@@ -10,8 +10,8 @@ Currently this network device driver is for all STM embedded MAC/GMAC | |||
10 | (i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000 | 10 | (i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000 |
11 | FF1152AMT0221 D1215994A VIRTEX FPGA board. | 11 | FF1152AMT0221 D1215994A VIRTEX FPGA board. |
12 | 12 | ||
13 | DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether MAC 10/100 | 13 | DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether |
14 | Universal version 4.0 have been used for developing this driver. | 14 | MAC 10/100 Universal version 4.0 have been used for developing this driver. |
15 | 15 | ||
16 | This driver supports both the platform bus and PCI. | 16 | This driver supports both the platform bus and PCI. |
17 | 17 | ||
@@ -54,27 +54,27 @@ net_device structure enabling the scatter/gather feature. | |||
54 | When one or more packets are received, an interrupt happens. The interrupts | 54 | When one or more packets are received, an interrupt happens. The interrupts |
55 | are not queued so the driver has to scan all the descriptors in the ring during | 55 | are not queued so the driver has to scan all the descriptors in the ring during |
56 | the receive process. | 56 | the receive process. |
57 | This is based on NAPI so the interrupt handler signals only if there is work to be | 57 | This is based on NAPI so the interrupt handler signals only if there is work |
58 | done, and it exits. | 58 | to be done, and it exits. |
59 | Then the poll method will be scheduled at some future point. | 59 | Then the poll method will be scheduled at some future point. |
60 | The incoming packets are stored, by the DMA, in a list of pre-allocated socket | 60 | The incoming packets are stored, by the DMA, in a list of pre-allocated socket |
61 | buffers in order to avoid the memcpy (Zero-copy). | 61 | buffers in order to avoid the memcpy (Zero-copy). |
62 | 62 | ||
63 | 4.3) Timer-Driver Interrupt | 63 | 4.3) Timer-Driver Interrupt |
64 | Instead of having the device that asynchronously notifies the frame receptions, the | 64 | Instead of having the device that asynchronously notifies the frame receptions, |
65 | driver configures a timer to generate an interrupt at regular intervals. | 65 | the driver configures a timer to generate an interrupt at regular intervals. |
66 | Based on the granularity of the timer, the frames that are received by the device | 66 | Based on the granularity of the timer, the frames that are received by the |
67 | will experience different levels of latency. Some NICs have dedicated timer | 67 | device will experience different levels of latency. Some NICs have dedicated |
68 | device to perform this task. STMMAC can use either the RTC device or the TMU | 68 | timer device to perform this task. STMMAC can use either the RTC device or the |
69 | channel 2 on STLinux platforms. | 69 | TMU channel 2 on STLinux platforms. |
70 | The timers frequency can be passed to the driver as parameter; when change it, | 70 | The timers frequency can be passed to the driver as parameter; when change it, |
71 | take care of both hardware capability and network stability/performance impact. | 71 | take care of both hardware capability and network stability/performance impact. |
72 | Several performance tests on STM platforms showed this optimisation allows to spare | 72 | Several performance tests on STM platforms showed this optimisation allows to |
73 | the CPU while having the maximum throughput. | 73 | spare the CPU while having the maximum throughput. |
74 | 74 | ||
75 | 4.4) WOL | 75 | 4.4) WOL |
76 | Wake up on Lan feature through Magic and Unicast frames are supported for the GMAC | 76 | Wake up on Lan feature through Magic and Unicast frames are supported for the |
77 | core. | 77 | GMAC core. |
78 | 78 | ||
79 | 4.5) DMA descriptors | 79 | 4.5) DMA descriptors |
80 | Driver handles both normal and enhanced descriptors. The latter has been only | 80 | Driver handles both normal and enhanced descriptors. The latter has been only |
@@ -106,7 +106,8 @@ Several driver's information can be passed through the platform | |||
106 | These are included in the include/linux/stmmac.h header file | 106 | These are included in the include/linux/stmmac.h header file |
107 | and detailed below as well: | 107 | and detailed below as well: |
108 | 108 | ||
109 | struct plat_stmmacenet_data { | 109 | struct plat_stmmacenet_data { |
110 | char *phy_bus_name; | ||
110 | int bus_id; | 111 | int bus_id; |
111 | int phy_addr; | 112 | int phy_addr; |
112 | int interface; | 113 | int interface; |
@@ -124,19 +125,24 @@ and detailed below as well: | |||
124 | void (*bus_setup)(void __iomem *ioaddr); | 125 | void (*bus_setup)(void __iomem *ioaddr); |
125 | int (*init)(struct platform_device *pdev); | 126 | int (*init)(struct platform_device *pdev); |
126 | void (*exit)(struct platform_device *pdev); | 127 | void (*exit)(struct platform_device *pdev); |
128 | void *custom_cfg; | ||
129 | void *custom_data; | ||
127 | void *bsp_priv; | 130 | void *bsp_priv; |
128 | }; | 131 | }; |
129 | 132 | ||
130 | Where: | 133 | Where: |
134 | o phy_bus_name: phy bus name to attach to the stmmac. | ||
131 | o bus_id: bus identifier. | 135 | o bus_id: bus identifier. |
132 | o phy_addr: the physical address can be passed from the platform. | 136 | o phy_addr: the physical address can be passed from the platform. |
133 | If it is set to -1 the driver will automatically | 137 | If it is set to -1 the driver will automatically |
134 | detect it at run-time by probing all the 32 addresses. | 138 | detect it at run-time by probing all the 32 addresses. |
135 | o interface: PHY device's interface. | 139 | o interface: PHY device's interface. |
136 | o mdio_bus_data: specific platform fields for the MDIO bus. | 140 | o mdio_bus_data: specific platform fields for the MDIO bus. |
137 | o pbl: the Programmable Burst Length is maximum number of beats to | 141 | o dma_cfg: internal DMA parameters |
142 | o pbl: the Programmable Burst Length is maximum number of beats to | ||
138 | be transferred in one DMA transaction. | 143 | be transferred in one DMA transaction. |
139 | GMAC also enables the 4xPBL by default. | 144 | GMAC also enables the 4xPBL by default. |
145 | o fixed_burst/mixed_burst/burst_len | ||
140 | o clk_csr: fixed CSR Clock range selection. | 146 | o clk_csr: fixed CSR Clock range selection. |
141 | o has_gmac: uses the GMAC core. | 147 | o has_gmac: uses the GMAC core. |
142 | o enh_desc: if sets the MAC will use the enhanced descriptor structure. | 148 | o enh_desc: if sets the MAC will use the enhanced descriptor structure. |
@@ -160,8 +166,9 @@ Where: | |||
160 | this is sometime necessary on some platforms (e.g. ST boxes) | 166 | this is sometime necessary on some platforms (e.g. ST boxes) |
161 | where the HW needs to have set some PIO lines or system cfg | 167 | where the HW needs to have set some PIO lines or system cfg |
162 | registers. | 168 | registers. |
163 | o custom_cfg: this is a custom configuration that can be passed while | 169 | o custom_cfg/custom_data: this is a custom configuration that can be passed |
164 | initialising the resources. | 170 | while initialising the resources. |
171 | o bsp_priv: another private poiter. | ||
165 | 172 | ||
166 | For MDIO bus The we have: | 173 | For MDIO bus The we have: |
167 | 174 | ||
@@ -180,7 +187,6 @@ Where: | |||
180 | o irqs: list of IRQs, one per PHY. | 187 | o irqs: list of IRQs, one per PHY. |
181 | o probed_phy_irq: if irqs is NULL, use this for probed PHY. | 188 | o probed_phy_irq: if irqs is NULL, use this for probed PHY. |
182 | 189 | ||
183 | |||
184 | For DMA engine we have the following internal fields that should be | 190 | For DMA engine we have the following internal fields that should be |
185 | tuned according to the HW capabilities. | 191 | tuned according to the HW capabilities. |
186 | 192 | ||
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index a058842f14fd..61ce4054b3c3 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c | |||
@@ -139,7 +139,9 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc) | |||
139 | bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); | 139 | bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); |
140 | break; | 140 | break; |
141 | case 0x4331: | 141 | case 0x4331: |
142 | /* BCM4331 workaround is SPROM-related, we put it in sprom.c */ | 142 | case 43431: |
143 | /* Ext PA lines must be enabled for tx on BCM4331 */ | ||
144 | bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true); | ||
143 | break; | 145 | break; |
144 | case 43224: | 146 | case 43224: |
145 | if (bus->chipinfo.rev == 0) { | 147 | if (bus->chipinfo.rev == 0) { |
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index c7f93359acb0..f16f42d36071 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
@@ -579,13 +579,13 @@ int bcma_sprom_get(struct bcma_bus *bus) | |||
579 | if (!sprom) | 579 | if (!sprom) |
580 | return -ENOMEM; | 580 | return -ENOMEM; |
581 | 581 | ||
582 | if (bus->chipinfo.id == 0x4331) | 582 | if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) |
583 | bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); | 583 | bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); |
584 | 584 | ||
585 | pr_debug("SPROM offset 0x%x\n", offset); | 585 | pr_debug("SPROM offset 0x%x\n", offset); |
586 | bcma_sprom_read(bus, offset, sprom); | 586 | bcma_sprom_read(bus, offset, sprom); |
587 | 587 | ||
588 | if (bus->chipinfo.id == 0x4331) | 588 | if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) |
589 | bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); | 589 | bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); |
590 | 590 | ||
591 | err = bcma_sprom_valid(sprom); | 591 | err = bcma_sprom_valid(sprom); |
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 536bda072a16..8dc84d66eea1 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c | |||
@@ -686,7 +686,7 @@ static int c_can_get_berr_counter(const struct net_device *dev, | |||
686 | * | 686 | * |
687 | * We iterate from priv->tx_echo to priv->tx_next and check if the | 687 | * We iterate from priv->tx_echo to priv->tx_next and check if the |
688 | * packet has been transmitted, echo it back to the CAN framework. | 688 | * packet has been transmitted, echo it back to the CAN framework. |
689 | * If we discover a not yet transmitted package, stop looking for more. | 689 | * If we discover a not yet transmitted packet, stop looking for more. |
690 | */ | 690 | */ |
691 | static void c_can_do_tx(struct net_device *dev) | 691 | static void c_can_do_tx(struct net_device *dev) |
692 | { | 692 | { |
@@ -698,7 +698,7 @@ static void c_can_do_tx(struct net_device *dev) | |||
698 | for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { | 698 | for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { |
699 | msg_obj_no = get_tx_echo_msg_obj(priv); | 699 | msg_obj_no = get_tx_echo_msg_obj(priv); |
700 | val = c_can_read_reg32(priv, &priv->regs->txrqst1); | 700 | val = c_can_read_reg32(priv, &priv->regs->txrqst1); |
701 | if (!(val & (1 << msg_obj_no))) { | 701 | if (!(val & (1 << (msg_obj_no - 1)))) { |
702 | can_get_echo_skb(dev, | 702 | can_get_echo_skb(dev, |
703 | msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); | 703 | msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); |
704 | stats->tx_bytes += priv->read_reg(priv, | 704 | stats->tx_bytes += priv->read_reg(priv, |
@@ -706,6 +706,8 @@ static void c_can_do_tx(struct net_device *dev) | |||
706 | & IF_MCONT_DLC_MASK; | 706 | & IF_MCONT_DLC_MASK; |
707 | stats->tx_packets++; | 707 | stats->tx_packets++; |
708 | c_can_inval_msg_object(dev, 0, msg_obj_no); | 708 | c_can_inval_msg_object(dev, 0, msg_obj_no); |
709 | } else { | ||
710 | break; | ||
709 | } | 711 | } |
710 | } | 712 | } |
711 | 713 | ||
@@ -950,7 +952,7 @@ static int c_can_poll(struct napi_struct *napi, int quota) | |||
950 | struct net_device *dev = napi->dev; | 952 | struct net_device *dev = napi->dev; |
951 | struct c_can_priv *priv = netdev_priv(dev); | 953 | struct c_can_priv *priv = netdev_priv(dev); |
952 | 954 | ||
953 | irqstatus = priv->read_reg(priv, &priv->regs->interrupt); | 955 | irqstatus = priv->irqstatus; |
954 | if (!irqstatus) | 956 | if (!irqstatus) |
955 | goto end; | 957 | goto end; |
956 | 958 | ||
@@ -1028,12 +1030,11 @@ end: | |||
1028 | 1030 | ||
1029 | static irqreturn_t c_can_isr(int irq, void *dev_id) | 1031 | static irqreturn_t c_can_isr(int irq, void *dev_id) |
1030 | { | 1032 | { |
1031 | u16 irqstatus; | ||
1032 | struct net_device *dev = (struct net_device *)dev_id; | 1033 | struct net_device *dev = (struct net_device *)dev_id; |
1033 | struct c_can_priv *priv = netdev_priv(dev); | 1034 | struct c_can_priv *priv = netdev_priv(dev); |
1034 | 1035 | ||
1035 | irqstatus = priv->read_reg(priv, &priv->regs->interrupt); | 1036 | priv->irqstatus = priv->read_reg(priv, &priv->regs->interrupt); |
1036 | if (!irqstatus) | 1037 | if (!priv->irqstatus) |
1037 | return IRQ_NONE; | 1038 | return IRQ_NONE; |
1038 | 1039 | ||
1039 | /* disable all interrupts and schedule the NAPI */ | 1040 | /* disable all interrupts and schedule the NAPI */ |
@@ -1063,10 +1064,11 @@ static int c_can_open(struct net_device *dev) | |||
1063 | goto exit_irq_fail; | 1064 | goto exit_irq_fail; |
1064 | } | 1065 | } |
1065 | 1066 | ||
1067 | napi_enable(&priv->napi); | ||
1068 | |||
1066 | /* start the c_can controller */ | 1069 | /* start the c_can controller */ |
1067 | c_can_start(dev); | 1070 | c_can_start(dev); |
1068 | 1071 | ||
1069 | napi_enable(&priv->napi); | ||
1070 | netif_start_queue(dev); | 1072 | netif_start_queue(dev); |
1071 | 1073 | ||
1072 | return 0; | 1074 | return 0; |
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 9b7fbef3d09a..5f32d34af507 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h | |||
@@ -76,6 +76,7 @@ struct c_can_priv { | |||
76 | unsigned int tx_next; | 76 | unsigned int tx_next; |
77 | unsigned int tx_echo; | 77 | unsigned int tx_echo; |
78 | void *priv; /* for board-specific data */ | 78 | void *priv; /* for board-specific data */ |
79 | u16 irqstatus; | ||
79 | }; | 80 | }; |
80 | 81 | ||
81 | struct net_device *alloc_c_can_dev(void); | 82 | struct net_device *alloc_c_can_dev(void); |
diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c index 53115eee8075..688371cda37a 100644 --- a/drivers/net/can/cc770/cc770_platform.c +++ b/drivers/net/can/cc770/cc770_platform.c | |||
@@ -154,7 +154,7 @@ static int __devinit cc770_get_platform_data(struct platform_device *pdev, | |||
154 | struct cc770_platform_data *pdata = pdev->dev.platform_data; | 154 | struct cc770_platform_data *pdata = pdev->dev.platform_data; |
155 | 155 | ||
156 | priv->can.clock.freq = pdata->osc_freq; | 156 | priv->can.clock.freq = pdata->osc_freq; |
157 | if (priv->cpu_interface | CPUIF_DSC) | 157 | if (priv->cpu_interface & CPUIF_DSC) |
158 | priv->can.clock.freq /= 2; | 158 | priv->can.clock.freq /= 2; |
159 | priv->clkout = pdata->cor; | 159 | priv->clkout = pdata->cor; |
160 | priv->bus_config = pdata->bcr; | 160 | priv->bus_config = pdata->bcr; |
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index d863075df7a4..905e2147d918 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c | |||
@@ -258,7 +258,8 @@ static int e1000_set_settings(struct net_device *netdev, | |||
258 | * When SoL/IDER sessions are active, autoneg/speed/duplex | 258 | * When SoL/IDER sessions are active, autoneg/speed/duplex |
259 | * cannot be changed | 259 | * cannot be changed |
260 | */ | 260 | */ |
261 | if (hw->phy.ops.check_reset_block(hw)) { | 261 | if (hw->phy.ops.check_reset_block && |
262 | hw->phy.ops.check_reset_block(hw)) { | ||
262 | e_err("Cannot change link characteristics when SoL/IDER is active.\n"); | 263 | e_err("Cannot change link characteristics when SoL/IDER is active.\n"); |
263 | return -EINVAL; | 264 | return -EINVAL; |
264 | } | 265 | } |
@@ -1615,7 +1616,8 @@ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) | |||
1615 | * PHY loopback cannot be performed if SoL/IDER | 1616 | * PHY loopback cannot be performed if SoL/IDER |
1616 | * sessions are active | 1617 | * sessions are active |
1617 | */ | 1618 | */ |
1618 | if (hw->phy.ops.check_reset_block(hw)) { | 1619 | if (hw->phy.ops.check_reset_block && |
1620 | hw->phy.ops.check_reset_block(hw)) { | ||
1619 | e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); | 1621 | e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); |
1620 | *data = 0; | 1622 | *data = 0; |
1621 | goto out; | 1623 | goto out; |
diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c index 026e8b3ab52e..a13439928488 100644 --- a/drivers/net/ethernet/intel/e1000e/mac.c +++ b/drivers/net/ethernet/intel/e1000e/mac.c | |||
@@ -709,7 +709,7 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw) | |||
709 | * In the case of the phy reset being blocked, we already have a link. | 709 | * In the case of the phy reset being blocked, we already have a link. |
710 | * We do not need to set it up again. | 710 | * We do not need to set it up again. |
711 | */ | 711 | */ |
712 | if (hw->phy.ops.check_reset_block(hw)) | 712 | if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) |
713 | return 0; | 713 | return 0; |
714 | 714 | ||
715 | /* | 715 | /* |
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index a4b0435b00dc..31d37a2b5ba8 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c | |||
@@ -6237,7 +6237,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
6237 | adapter->hw.phy.ms_type = e1000_ms_hw_default; | 6237 | adapter->hw.phy.ms_type = e1000_ms_hw_default; |
6238 | } | 6238 | } |
6239 | 6239 | ||
6240 | if (hw->phy.ops.check_reset_block(hw)) | 6240 | if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) |
6241 | e_info("PHY reset is blocked due to SOL/IDER session.\n"); | 6241 | e_info("PHY reset is blocked due to SOL/IDER session.\n"); |
6242 | 6242 | ||
6243 | /* Set initial default active device features */ | 6243 | /* Set initial default active device features */ |
@@ -6404,7 +6404,7 @@ err_register: | |||
6404 | if (!(adapter->flags & FLAG_HAS_AMT)) | 6404 | if (!(adapter->flags & FLAG_HAS_AMT)) |
6405 | e1000e_release_hw_control(adapter); | 6405 | e1000e_release_hw_control(adapter); |
6406 | err_eeprom: | 6406 | err_eeprom: |
6407 | if (!hw->phy.ops.check_reset_block(hw)) | 6407 | if (hw->phy.ops.check_reset_block && !hw->phy.ops.check_reset_block(hw)) |
6408 | e1000_phy_hw_reset(&adapter->hw); | 6408 | e1000_phy_hw_reset(&adapter->hw); |
6409 | err_hw_init: | 6409 | err_hw_init: |
6410 | kfree(adapter->tx_ring); | 6410 | kfree(adapter->tx_ring); |
diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c index 0334d013bc3c..b860d4f7ea2a 100644 --- a/drivers/net/ethernet/intel/e1000e/phy.c +++ b/drivers/net/ethernet/intel/e1000e/phy.c | |||
@@ -2155,9 +2155,11 @@ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw) | |||
2155 | s32 ret_val; | 2155 | s32 ret_val; |
2156 | u32 ctrl; | 2156 | u32 ctrl; |
2157 | 2157 | ||
2158 | ret_val = phy->ops.check_reset_block(hw); | 2158 | if (phy->ops.check_reset_block) { |
2159 | if (ret_val) | 2159 | ret_val = phy->ops.check_reset_block(hw); |
2160 | return 0; | 2160 | if (ret_val) |
2161 | return 0; | ||
2162 | } | ||
2161 | 2163 | ||
2162 | ret_val = phy->ops.acquire(hw); | 2164 | ret_val = phy->ops.acquire(hw); |
2163 | if (ret_val) | 2165 | if (ret_val) |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index bf20457ea23a..17ad6a3c1be1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -1390,6 +1390,8 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, | |||
1390 | union ixgbe_adv_rx_desc *rx_desc, | 1390 | union ixgbe_adv_rx_desc *rx_desc, |
1391 | struct sk_buff *skb) | 1391 | struct sk_buff *skb) |
1392 | { | 1392 | { |
1393 | struct net_device *dev = rx_ring->netdev; | ||
1394 | |||
1393 | ixgbe_update_rsc_stats(rx_ring, skb); | 1395 | ixgbe_update_rsc_stats(rx_ring, skb); |
1394 | 1396 | ||
1395 | ixgbe_rx_hash(rx_ring, rx_desc, skb); | 1397 | ixgbe_rx_hash(rx_ring, rx_desc, skb); |
@@ -1401,14 +1403,15 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, | |||
1401 | ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb); | 1403 | ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb); |
1402 | #endif | 1404 | #endif |
1403 | 1405 | ||
1404 | if (ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { | 1406 | if ((dev->features & NETIF_F_HW_VLAN_RX) && |
1407 | ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { | ||
1405 | u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan); | 1408 | u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan); |
1406 | __vlan_hwaccel_put_tag(skb, vid); | 1409 | __vlan_hwaccel_put_tag(skb, vid); |
1407 | } | 1410 | } |
1408 | 1411 | ||
1409 | skb_record_rx_queue(skb, rx_ring->queue_index); | 1412 | skb_record_rx_queue(skb, rx_ring->queue_index); |
1410 | 1413 | ||
1411 | skb->protocol = eth_type_trans(skb, rx_ring->netdev); | 1414 | skb->protocol = eth_type_trans(skb, dev); |
1412 | } | 1415 | } |
1413 | 1416 | ||
1414 | static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector, | 1417 | static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector, |
@@ -3607,10 +3610,6 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) | |||
3607 | if (hw->mac.type == ixgbe_mac_82598EB) | 3610 | if (hw->mac.type == ixgbe_mac_82598EB) |
3608 | netif_set_gso_max_size(adapter->netdev, 32768); | 3611 | netif_set_gso_max_size(adapter->netdev, 32768); |
3609 | 3612 | ||
3610 | |||
3611 | /* Enable VLAN tag insert/strip */ | ||
3612 | adapter->netdev->features |= NETIF_F_HW_VLAN_RX; | ||
3613 | |||
3614 | hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true); | 3613 | hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true); |
3615 | 3614 | ||
3616 | #ifdef IXGBE_FCOE | 3615 | #ifdef IXGBE_FCOE |
@@ -6701,11 +6700,6 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev, | |||
6701 | { | 6700 | { |
6702 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 6701 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
6703 | 6702 | ||
6704 | #ifdef CONFIG_DCB | ||
6705 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) | ||
6706 | features &= ~NETIF_F_HW_VLAN_RX; | ||
6707 | #endif | ||
6708 | |||
6709 | /* return error if RXHASH is being enabled when RSS is not supported */ | 6703 | /* return error if RXHASH is being enabled when RSS is not supported */ |
6710 | if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) | 6704 | if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) |
6711 | features &= ~NETIF_F_RXHASH; | 6705 | features &= ~NETIF_F_RXHASH; |
@@ -6718,7 +6712,6 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev, | |||
6718 | if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) | 6712 | if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) |
6719 | features &= ~NETIF_F_LRO; | 6713 | features &= ~NETIF_F_LRO; |
6720 | 6714 | ||
6721 | |||
6722 | return features; | 6715 | return features; |
6723 | } | 6716 | } |
6724 | 6717 | ||
@@ -6766,6 +6759,11 @@ static int ixgbe_set_features(struct net_device *netdev, | |||
6766 | need_reset = true; | 6759 | need_reset = true; |
6767 | } | 6760 | } |
6768 | 6761 | ||
6762 | if (features & NETIF_F_HW_VLAN_RX) | ||
6763 | ixgbe_vlan_strip_enable(adapter); | ||
6764 | else | ||
6765 | ixgbe_vlan_strip_disable(adapter); | ||
6766 | |||
6769 | if (changed & NETIF_F_RXALL) | 6767 | if (changed & NETIF_F_RXALL) |
6770 | need_reset = true; | 6768 | need_reset = true; |
6771 | 6769 | ||
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index ec85bf1bffd1..770ee557924c 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c | |||
@@ -436,7 +436,9 @@ struct mv643xx_eth_private { | |||
436 | /* | 436 | /* |
437 | * Hardware-specific parameters. | 437 | * Hardware-specific parameters. |
438 | */ | 438 | */ |
439 | #if defined(CONFIG_HAVE_CLK) | ||
439 | struct clk *clk; | 440 | struct clk *clk; |
441 | #endif | ||
440 | unsigned int t_clk; | 442 | unsigned int t_clk; |
441 | }; | 443 | }; |
442 | 444 | ||
@@ -2895,17 +2897,17 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
2895 | mp->dev = dev; | 2897 | mp->dev = dev; |
2896 | 2898 | ||
2897 | /* | 2899 | /* |
2898 | * Get the clk rate, if there is one, otherwise use the default. | 2900 | * Start with a default rate, and if there is a clock, allow |
2901 | * it to override the default. | ||
2899 | */ | 2902 | */ |
2903 | mp->t_clk = 133000000; | ||
2904 | #if defined(CONFIG_HAVE_CLK) | ||
2900 | mp->clk = clk_get(&pdev->dev, (pdev->id ? "1" : "0")); | 2905 | mp->clk = clk_get(&pdev->dev, (pdev->id ? "1" : "0")); |
2901 | if (!IS_ERR(mp->clk)) { | 2906 | if (!IS_ERR(mp->clk)) { |
2902 | clk_prepare_enable(mp->clk); | 2907 | clk_prepare_enable(mp->clk); |
2903 | mp->t_clk = clk_get_rate(mp->clk); | 2908 | mp->t_clk = clk_get_rate(mp->clk); |
2904 | } else { | ||
2905 | mp->t_clk = 133000000; | ||
2906 | printk(KERN_WARNING "Unable to get clock"); | ||
2907 | } | 2909 | } |
2908 | 2910 | #endif | |
2909 | set_params(mp, pd); | 2911 | set_params(mp, pd); |
2910 | netif_set_real_num_tx_queues(dev, mp->txq_count); | 2912 | netif_set_real_num_tx_queues(dev, mp->txq_count); |
2911 | netif_set_real_num_rx_queues(dev, mp->rxq_count); | 2913 | netif_set_real_num_rx_queues(dev, mp->rxq_count); |
@@ -2995,10 +2997,13 @@ static int mv643xx_eth_remove(struct platform_device *pdev) | |||
2995 | phy_detach(mp->phy); | 2997 | phy_detach(mp->phy); |
2996 | cancel_work_sync(&mp->tx_timeout_task); | 2998 | cancel_work_sync(&mp->tx_timeout_task); |
2997 | 2999 | ||
3000 | #if defined(CONFIG_HAVE_CLK) | ||
2998 | if (!IS_ERR(mp->clk)) { | 3001 | if (!IS_ERR(mp->clk)) { |
2999 | clk_disable_unprepare(mp->clk); | 3002 | clk_disable_unprepare(mp->clk); |
3000 | clk_put(mp->clk); | 3003 | clk_put(mp->clk); |
3001 | } | 3004 | } |
3005 | #endif | ||
3006 | |||
3002 | free_netdev(mp->dev); | 3007 | free_netdev(mp->dev); |
3003 | 3008 | ||
3004 | platform_set_drvdata(pdev, NULL); | 3009 | platform_set_drvdata(pdev, NULL); |
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 036428348faa..0076f770e637 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig | |||
@@ -13,9 +13,8 @@ config STMMAC_ETH | |||
13 | if STMMAC_ETH | 13 | if STMMAC_ETH |
14 | 14 | ||
15 | config STMMAC_PLATFORM | 15 | config STMMAC_PLATFORM |
16 | tristate "STMMAC platform bus support" | 16 | bool "STMMAC Platform bus support" |
17 | depends on STMMAC_ETH | 17 | depends on STMMAC_ETH |
18 | default y | ||
19 | ---help--- | 18 | ---help--- |
20 | This selects the platform specific bus support for | 19 | This selects the platform specific bus support for |
21 | the stmmac device driver. This is the driver used | 20 | the stmmac device driver. This is the driver used |
@@ -26,7 +25,7 @@ config STMMAC_PLATFORM | |||
26 | If unsure, say N. | 25 | If unsure, say N. |
27 | 26 | ||
28 | config STMMAC_PCI | 27 | config STMMAC_PCI |
29 | tristate "STMMAC support on PCI bus (EXPERIMENTAL)" | 28 | bool "STMMAC PCI bus support (EXPERIMENTAL)" |
30 | depends on STMMAC_ETH && PCI && EXPERIMENTAL | 29 | depends on STMMAC_ETH && PCI && EXPERIMENTAL |
31 | ---help--- | 30 | ---help--- |
32 | This is to select the Synopsys DWMAC available on PCI devices, | 31 | This is to select the Synopsys DWMAC available on PCI devices, |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 6b5d060ee9de..6d07ba2c8661 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h | |||
@@ -95,7 +95,8 @@ extern int stmmac_mdio_register(struct net_device *ndev); | |||
95 | extern void stmmac_set_ethtool_ops(struct net_device *netdev); | 95 | extern void stmmac_set_ethtool_ops(struct net_device *netdev); |
96 | extern const struct stmmac_desc_ops enh_desc_ops; | 96 | extern const struct stmmac_desc_ops enh_desc_ops; |
97 | extern const struct stmmac_desc_ops ndesc_ops; | 97 | extern const struct stmmac_desc_ops ndesc_ops; |
98 | 98 | extern struct pci_driver stmmac_pci_driver; | |
99 | extern struct platform_driver stmmac_pltfr_driver; | ||
99 | int stmmac_freeze(struct net_device *ndev); | 100 | int stmmac_freeze(struct net_device *ndev); |
100 | int stmmac_restore(struct net_device *ndev); | 101 | int stmmac_restore(struct net_device *ndev); |
101 | int stmmac_resume(struct net_device *ndev); | 102 | int stmmac_resume(struct net_device *ndev); |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 0caae72cda89..8899e105da9f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/dma-mapping.h> | 42 | #include <linux/dma-mapping.h> |
43 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
44 | #include <linux/prefetch.h> | 44 | #include <linux/prefetch.h> |
45 | #include <linux/pci.h> | ||
45 | #ifdef CONFIG_STMMAC_DEBUG_FS | 46 | #ifdef CONFIG_STMMAC_DEBUG_FS |
46 | #include <linux/debugfs.h> | 47 | #include <linux/debugfs.h> |
47 | #include <linux/seq_file.h> | 48 | #include <linux/seq_file.h> |
@@ -833,8 +834,9 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) | |||
833 | 834 | ||
834 | /** | 835 | /** |
835 | * stmmac_selec_desc_mode | 836 | * stmmac_selec_desc_mode |
836 | * @dev : device pointer | 837 | * @priv : private structure |
837 | * Description: select the Enhanced/Alternate or Normal descriptors */ | 838 | * Description: select the Enhanced/Alternate or Normal descriptors |
839 | */ | ||
838 | static void stmmac_selec_desc_mode(struct stmmac_priv *priv) | 840 | static void stmmac_selec_desc_mode(struct stmmac_priv *priv) |
839 | { | 841 | { |
840 | if (priv->plat->enh_desc) { | 842 | if (priv->plat->enh_desc) { |
@@ -1860,6 +1862,8 @@ static int stmmac_hw_init(struct stmmac_priv *priv) | |||
1860 | /** | 1862 | /** |
1861 | * stmmac_dvr_probe | 1863 | * stmmac_dvr_probe |
1862 | * @device: device pointer | 1864 | * @device: device pointer |
1865 | * @plat_dat: platform data pointer | ||
1866 | * @addr: iobase memory address | ||
1863 | * Description: this is the main probe function used to | 1867 | * Description: this is the main probe function used to |
1864 | * call the alloc_etherdev, allocate the priv structure. | 1868 | * call the alloc_etherdev, allocate the priv structure. |
1865 | */ | 1869 | */ |
@@ -2089,6 +2093,30 @@ int stmmac_restore(struct net_device *ndev) | |||
2089 | } | 2093 | } |
2090 | #endif /* CONFIG_PM */ | 2094 | #endif /* CONFIG_PM */ |
2091 | 2095 | ||
2096 | static int __init stmmac_init(void) | ||
2097 | { | ||
2098 | int err = 0; | ||
2099 | |||
2100 | err = platform_driver_register(&stmmac_pltfr_driver); | ||
2101 | |||
2102 | if (!err) { | ||
2103 | err = pci_register_driver(&stmmac_pci_driver); | ||
2104 | if (err) | ||
2105 | platform_driver_unregister(&stmmac_pltfr_driver); | ||
2106 | } | ||
2107 | |||
2108 | return err; | ||
2109 | } | ||
2110 | |||
2111 | static void __exit stmmac_exit(void) | ||
2112 | { | ||
2113 | pci_unregister_driver(&stmmac_pci_driver); | ||
2114 | platform_driver_unregister(&stmmac_pltfr_driver); | ||
2115 | } | ||
2116 | |||
2117 | module_init(stmmac_init); | ||
2118 | module_exit(stmmac_exit); | ||
2119 | |||
2092 | #ifndef MODULE | 2120 | #ifndef MODULE |
2093 | static int __init stmmac_cmdline_opt(char *str) | 2121 | static int __init stmmac_cmdline_opt(char *str) |
2094 | { | 2122 | { |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index 58fab5303e9c..cf826e6b6aa1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | |||
@@ -179,7 +179,7 @@ static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = { | |||
179 | 179 | ||
180 | MODULE_DEVICE_TABLE(pci, stmmac_id_table); | 180 | MODULE_DEVICE_TABLE(pci, stmmac_id_table); |
181 | 181 | ||
182 | static struct pci_driver stmmac_driver = { | 182 | struct pci_driver stmmac_pci_driver = { |
183 | .name = STMMAC_RESOURCE_NAME, | 183 | .name = STMMAC_RESOURCE_NAME, |
184 | .id_table = stmmac_id_table, | 184 | .id_table = stmmac_id_table, |
185 | .probe = stmmac_pci_probe, | 185 | .probe = stmmac_pci_probe, |
@@ -190,33 +190,6 @@ static struct pci_driver stmmac_driver = { | |||
190 | #endif | 190 | #endif |
191 | }; | 191 | }; |
192 | 192 | ||
193 | /** | ||
194 | * stmmac_init_module - Entry point for the driver | ||
195 | * Description: This function is the entry point for the driver. | ||
196 | */ | ||
197 | static int __init stmmac_init_module(void) | ||
198 | { | ||
199 | int ret; | ||
200 | |||
201 | ret = pci_register_driver(&stmmac_driver); | ||
202 | if (ret < 0) | ||
203 | pr_err("%s: ERROR: driver registration failed\n", __func__); | ||
204 | |||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * stmmac_cleanup_module - Cleanup routine for the driver | ||
210 | * Description: This function is the cleanup routine for the driver. | ||
211 | */ | ||
212 | static void __exit stmmac_cleanup_module(void) | ||
213 | { | ||
214 | pci_unregister_driver(&stmmac_driver); | ||
215 | } | ||
216 | |||
217 | module_init(stmmac_init_module); | ||
218 | module_exit(stmmac_cleanup_module); | ||
219 | |||
220 | MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver"); | 193 | MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver"); |
221 | MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>"); | 194 | MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>"); |
222 | MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); | 195 | MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index df4774d5f6a7..20eb5026c49c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | |||
@@ -255,7 +255,7 @@ static const struct of_device_id stmmac_dt_ids[] = { | |||
255 | }; | 255 | }; |
256 | MODULE_DEVICE_TABLE(of, stmmac_dt_ids); | 256 | MODULE_DEVICE_TABLE(of, stmmac_dt_ids); |
257 | 257 | ||
258 | static struct platform_driver stmmac_driver = { | 258 | struct platform_driver stmmac_pltfr_driver = { |
259 | .probe = stmmac_pltfr_probe, | 259 | .probe = stmmac_pltfr_probe, |
260 | .remove = stmmac_pltfr_remove, | 260 | .remove = stmmac_pltfr_remove, |
261 | .driver = { | 261 | .driver = { |
@@ -266,8 +266,6 @@ static struct platform_driver stmmac_driver = { | |||
266 | }, | 266 | }, |
267 | }; | 267 | }; |
268 | 268 | ||
269 | module_platform_driver(stmmac_driver); | ||
270 | |||
271 | MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver"); | 269 | MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver"); |
272 | MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); | 270 | MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); |
273 | MODULE_LICENSE("GPL"); | 271 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 4ffcd57b011b..2857ab078aac 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h | |||
@@ -478,6 +478,7 @@ struct netvsc_device { | |||
478 | u32 nvsp_version; | 478 | u32 nvsp_version; |
479 | 479 | ||
480 | atomic_t num_outstanding_sends; | 480 | atomic_t num_outstanding_sends; |
481 | wait_queue_head_t wait_drain; | ||
481 | bool start_remove; | 482 | bool start_remove; |
482 | bool destroy; | 483 | bool destroy; |
483 | /* | 484 | /* |
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 4363c76e0d63..6cee2917eb02 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c | |||
@@ -42,6 +42,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) | |||
42 | if (!net_device) | 42 | if (!net_device) |
43 | return NULL; | 43 | return NULL; |
44 | 44 | ||
45 | init_waitqueue_head(&net_device->wait_drain); | ||
45 | net_device->start_remove = false; | 46 | net_device->start_remove = false; |
46 | net_device->destroy = false; | 47 | net_device->destroy = false; |
47 | net_device->dev = device; | 48 | net_device->dev = device; |
@@ -387,12 +388,8 @@ int netvsc_device_remove(struct hv_device *device) | |||
387 | spin_unlock_irqrestore(&device->channel->inbound_lock, flags); | 388 | spin_unlock_irqrestore(&device->channel->inbound_lock, flags); |
388 | 389 | ||
389 | /* Wait for all send completions */ | 390 | /* Wait for all send completions */ |
390 | while (atomic_read(&net_device->num_outstanding_sends)) { | 391 | wait_event(net_device->wait_drain, |
391 | dev_info(&device->device, | 392 | atomic_read(&net_device->num_outstanding_sends) == 0); |
392 | "waiting for %d requests to complete...\n", | ||
393 | atomic_read(&net_device->num_outstanding_sends)); | ||
394 | udelay(100); | ||
395 | } | ||
396 | 393 | ||
397 | netvsc_disconnect_vsp(net_device); | 394 | netvsc_disconnect_vsp(net_device); |
398 | 395 | ||
@@ -486,6 +483,9 @@ static void netvsc_send_completion(struct hv_device *device, | |||
486 | num_outstanding_sends = | 483 | num_outstanding_sends = |
487 | atomic_dec_return(&net_device->num_outstanding_sends); | 484 | atomic_dec_return(&net_device->num_outstanding_sends); |
488 | 485 | ||
486 | if (net_device->destroy && num_outstanding_sends == 0) | ||
487 | wake_up(&net_device->wait_drain); | ||
488 | |||
489 | if (netif_queue_stopped(ndev) && !net_device->start_remove && | 489 | if (netif_queue_stopped(ndev) && !net_device->start_remove && |
490 | (hv_ringbuf_avail_percent(&device->channel->outbound) | 490 | (hv_ringbuf_avail_percent(&device->channel->outbound) |
491 | > RING_AVAIL_PERCENT_HIWATER || | 491 | > RING_AVAIL_PERCENT_HIWATER || |
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c index 5ac46f5226f3..47f8e8939266 100644 --- a/drivers/net/phy/icplus.c +++ b/drivers/net/phy/icplus.c | |||
@@ -41,6 +41,8 @@ MODULE_LICENSE("GPL"); | |||
41 | #define IP1001_APS_ON 11 /* IP1001 APS Mode bit */ | 41 | #define IP1001_APS_ON 11 /* IP1001 APS Mode bit */ |
42 | #define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */ | 42 | #define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */ |
43 | #define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ | 43 | #define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ |
44 | #define IP101A_G_IRQ_PIN_USED (1<<15) /* INTR pin used */ | ||
45 | #define IP101A_G_IRQ_DEFAULT IP101A_G_IRQ_PIN_USED | ||
44 | 46 | ||
45 | static int ip175c_config_init(struct phy_device *phydev) | 47 | static int ip175c_config_init(struct phy_device *phydev) |
46 | { | 48 | { |
@@ -136,6 +138,11 @@ static int ip1001_config_init(struct phy_device *phydev) | |||
136 | if (c < 0) | 138 | if (c < 0) |
137 | return c; | 139 | return c; |
138 | 140 | ||
141 | /* INTR pin used: speed/link/duplex will cause an interrupt */ | ||
142 | c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT); | ||
143 | if (c < 0) | ||
144 | return c; | ||
145 | |||
139 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { | 146 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { |
140 | /* Additional delay (2ns) used to adjust RX clock phase | 147 | /* Additional delay (2ns) used to adjust RX clock phase |
141 | * at RGMII interface */ | 148 | * at RGMII interface */ |
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index 3faef5670d1f..d75d1f56becf 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c | |||
@@ -946,7 +946,7 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | |||
946 | } | 946 | } |
947 | 947 | ||
948 | static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; | 948 | static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; |
949 | static const struct sierra_net_info_data sierra_net_info_data_68A3 = { | 949 | static const struct sierra_net_info_data sierra_net_info_data_direct_ip = { |
950 | .rx_urb_size = 8 * 1024, | 950 | .rx_urb_size = 8 * 1024, |
951 | .whitelist = { | 951 | .whitelist = { |
952 | .infolen = ARRAY_SIZE(sierra_net_ifnum_list), | 952 | .infolen = ARRAY_SIZE(sierra_net_ifnum_list), |
@@ -954,7 +954,7 @@ static const struct sierra_net_info_data sierra_net_info_data_68A3 = { | |||
954 | } | 954 | } |
955 | }; | 955 | }; |
956 | 956 | ||
957 | static const struct driver_info sierra_net_info_68A3 = { | 957 | static const struct driver_info sierra_net_info_direct_ip = { |
958 | .description = "Sierra Wireless USB-to-WWAN Modem", | 958 | .description = "Sierra Wireless USB-to-WWAN Modem", |
959 | .flags = FLAG_WWAN | FLAG_SEND_ZLP, | 959 | .flags = FLAG_WWAN | FLAG_SEND_ZLP, |
960 | .bind = sierra_net_bind, | 960 | .bind = sierra_net_bind, |
@@ -962,12 +962,18 @@ static const struct driver_info sierra_net_info_68A3 = { | |||
962 | .status = sierra_net_status, | 962 | .status = sierra_net_status, |
963 | .rx_fixup = sierra_net_rx_fixup, | 963 | .rx_fixup = sierra_net_rx_fixup, |
964 | .tx_fixup = sierra_net_tx_fixup, | 964 | .tx_fixup = sierra_net_tx_fixup, |
965 | .data = (unsigned long)&sierra_net_info_data_68A3, | 965 | .data = (unsigned long)&sierra_net_info_data_direct_ip, |
966 | }; | 966 | }; |
967 | 967 | ||
968 | static const struct usb_device_id products[] = { | 968 | static const struct usb_device_id products[] = { |
969 | {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ | 969 | {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ |
970 | .driver_info = (unsigned long) &sierra_net_info_68A3}, | 970 | .driver_info = (unsigned long) &sierra_net_info_direct_ip}, |
971 | {USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ | ||
972 | .driver_info = (unsigned long) &sierra_net_info_direct_ip}, | ||
973 | {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ | ||
974 | .driver_info = (unsigned long) &sierra_net_info_direct_ip}, | ||
975 | {USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ | ||
976 | .driver_info = (unsigned long) &sierra_net_info_direct_ip}, | ||
971 | 977 | ||
972 | {}, /* last item */ | 978 | {}, /* last item */ |
973 | }; | 979 | }; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index e2480d196276..8e7e6928c936 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -89,9 +89,9 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | |||
89 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; | 89 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; |
90 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); | 90 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); |
91 | 91 | ||
92 | /* redirect, configure ane enable io for interrupt signal */ | 92 | /* redirect, configure and enable io for interrupt signal */ |
93 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; | 93 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; |
94 | if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH) | 94 | if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH) |
95 | data |= SDIO_SEPINT_ACT_HI; | 95 | data |= SDIO_SEPINT_ACT_HI; |
96 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); | 96 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); |
97 | 97 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index d742900969ea..fac67a526a30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -861,13 +861,18 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
861 | 861 | ||
862 | /* We have our copies now, allow OS release its copies */ | 862 | /* We have our copies now, allow OS release its copies */ |
863 | release_firmware(ucode_raw); | 863 | release_firmware(ucode_raw); |
864 | complete(&drv->request_firmware_complete); | ||
865 | 864 | ||
866 | drv->op_mode = iwl_dvm_ops.start(drv->trans, drv->cfg, &drv->fw); | 865 | drv->op_mode = iwl_dvm_ops.start(drv->trans, drv->cfg, &drv->fw); |
867 | 866 | ||
868 | if (!drv->op_mode) | 867 | if (!drv->op_mode) |
869 | goto out_free_fw; | 868 | goto out_unbind; |
870 | 869 | ||
870 | /* | ||
871 | * Complete the firmware request last so that | ||
872 | * a driver unbind (stop) doesn't run while we | ||
873 | * are doing the start() above. | ||
874 | */ | ||
875 | complete(&drv->request_firmware_complete); | ||
871 | return; | 876 | return; |
872 | 877 | ||
873 | try_again: | 878 | try_again: |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 50c58911e718..b8e2b223ac36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -568,28 +568,28 @@ static int iwl_find_otp_image(struct iwl_trans *trans, | |||
568 | * iwl_get_max_txpower_avg - get the highest tx power from all chains. | 568 | * iwl_get_max_txpower_avg - get the highest tx power from all chains. |
569 | * find the highest tx power from all chains for the channel | 569 | * find the highest tx power from all chains for the channel |
570 | */ | 570 | */ |
571 | static s8 iwl_get_max_txpower_avg(const struct iwl_cfg *cfg, | 571 | static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, |
572 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | 572 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, |
573 | int element, s8 *max_txpower_in_half_dbm) | 573 | int element, s8 *max_txpower_in_half_dbm) |
574 | { | 574 | { |
575 | s8 max_txpower_avg = 0; /* (dBm) */ | 575 | s8 max_txpower_avg = 0; /* (dBm) */ |
576 | 576 | ||
577 | /* Take the highest tx power from any valid chains */ | 577 | /* Take the highest tx power from any valid chains */ |
578 | if ((cfg->valid_tx_ant & ANT_A) && | 578 | if ((priv->hw_params.valid_tx_ant & ANT_A) && |
579 | (enhanced_txpower[element].chain_a_max > max_txpower_avg)) | 579 | (enhanced_txpower[element].chain_a_max > max_txpower_avg)) |
580 | max_txpower_avg = enhanced_txpower[element].chain_a_max; | 580 | max_txpower_avg = enhanced_txpower[element].chain_a_max; |
581 | if ((cfg->valid_tx_ant & ANT_B) && | 581 | if ((priv->hw_params.valid_tx_ant & ANT_B) && |
582 | (enhanced_txpower[element].chain_b_max > max_txpower_avg)) | 582 | (enhanced_txpower[element].chain_b_max > max_txpower_avg)) |
583 | max_txpower_avg = enhanced_txpower[element].chain_b_max; | 583 | max_txpower_avg = enhanced_txpower[element].chain_b_max; |
584 | if ((cfg->valid_tx_ant & ANT_C) && | 584 | if ((priv->hw_params.valid_tx_ant & ANT_C) && |
585 | (enhanced_txpower[element].chain_c_max > max_txpower_avg)) | 585 | (enhanced_txpower[element].chain_c_max > max_txpower_avg)) |
586 | max_txpower_avg = enhanced_txpower[element].chain_c_max; | 586 | max_txpower_avg = enhanced_txpower[element].chain_c_max; |
587 | if (((cfg->valid_tx_ant == ANT_AB) | | 587 | if (((priv->hw_params.valid_tx_ant == ANT_AB) | |
588 | (cfg->valid_tx_ant == ANT_BC) | | 588 | (priv->hw_params.valid_tx_ant == ANT_BC) | |
589 | (cfg->valid_tx_ant == ANT_AC)) && | 589 | (priv->hw_params.valid_tx_ant == ANT_AC)) && |
590 | (enhanced_txpower[element].mimo2_max > max_txpower_avg)) | 590 | (enhanced_txpower[element].mimo2_max > max_txpower_avg)) |
591 | max_txpower_avg = enhanced_txpower[element].mimo2_max; | 591 | max_txpower_avg = enhanced_txpower[element].mimo2_max; |
592 | if ((cfg->valid_tx_ant == ANT_ABC) && | 592 | if ((priv->hw_params.valid_tx_ant == ANT_ABC) && |
593 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) | 593 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) |
594 | max_txpower_avg = enhanced_txpower[element].mimo3_max; | 594 | max_txpower_avg = enhanced_txpower[element].mimo3_max; |
595 | 595 | ||
@@ -691,7 +691,7 @@ static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | |||
691 | ((txp->delta_20_in_40 & 0xf0) >> 4), | 691 | ((txp->delta_20_in_40 & 0xf0) >> 4), |
692 | (txp->delta_20_in_40 & 0x0f)); | 692 | (txp->delta_20_in_40 & 0x0f)); |
693 | 693 | ||
694 | max_txp_avg = iwl_get_max_txpower_avg(priv->cfg, txp_array, idx, | 694 | max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx, |
695 | &max_txp_avg_halfdbm); | 695 | &max_txp_avg_halfdbm); |
696 | 696 | ||
697 | /* | 697 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index ab2f4d7500a4..3ee23134c02b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c | |||
@@ -199,6 +199,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
199 | WIPHY_FLAG_DISABLE_BEACON_HINTS | | 199 | WIPHY_FLAG_DISABLE_BEACON_HINTS | |
200 | WIPHY_FLAG_IBSS_RSN; | 200 | WIPHY_FLAG_IBSS_RSN; |
201 | 201 | ||
202 | #ifdef CONFIG_PM_SLEEP | ||
202 | if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && | 203 | if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && |
203 | priv->trans->ops->wowlan_suspend && | 204 | priv->trans->ops->wowlan_suspend && |
204 | device_can_wakeup(priv->trans->dev)) { | 205 | device_can_wakeup(priv->trans->dev)) { |
@@ -217,6 +218,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
217 | hw->wiphy->wowlan.pattern_max_len = | 218 | hw->wiphy->wowlan.pattern_max_len = |
218 | IWLAGN_WOWLAN_MAX_PATTERN_LEN; | 219 | IWLAGN_WOWLAN_MAX_PATTERN_LEN; |
219 | } | 220 | } |
221 | #endif | ||
220 | 222 | ||
221 | if (iwlwifi_mod_params.power_save) | 223 | if (iwlwifi_mod_params.power_save) |
222 | hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; | 224 | hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; |
@@ -249,6 +251,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
249 | ret = ieee80211_register_hw(priv->hw); | 251 | ret = ieee80211_register_hw(priv->hw); |
250 | if (ret) { | 252 | if (ret) { |
251 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | 253 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); |
254 | iwl_leds_exit(priv); | ||
252 | return ret; | 255 | return ret; |
253 | } | 256 | } |
254 | priv->mac80211_registered = 1; | 257 | priv->mac80211_registered = 1; |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index fb787df01666..4c9336cee817 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -1721,6 +1721,24 @@ static void hwsim_exit_netlink(void) | |||
1721 | "unregister family %i\n", ret); | 1721 | "unregister family %i\n", ret); |
1722 | } | 1722 | } |
1723 | 1723 | ||
1724 | static const struct ieee80211_iface_limit hwsim_if_limits[] = { | ||
1725 | { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, | ||
1726 | { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) | | ||
1727 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
1728 | #ifdef CONFIG_MAC80211_MESH | ||
1729 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
1730 | #endif | ||
1731 | BIT(NL80211_IFTYPE_AP) | | ||
1732 | BIT(NL80211_IFTYPE_P2P_GO) }, | ||
1733 | }; | ||
1734 | |||
1735 | static const struct ieee80211_iface_combination hwsim_if_comb = { | ||
1736 | .limits = hwsim_if_limits, | ||
1737 | .n_limits = ARRAY_SIZE(hwsim_if_limits), | ||
1738 | .max_interfaces = 2048, | ||
1739 | .num_different_channels = 1, | ||
1740 | }; | ||
1741 | |||
1724 | static int __init init_mac80211_hwsim(void) | 1742 | static int __init init_mac80211_hwsim(void) |
1725 | { | 1743 | { |
1726 | int i, err = 0; | 1744 | int i, err = 0; |
@@ -1782,6 +1800,9 @@ static int __init init_mac80211_hwsim(void) | |||
1782 | hw->wiphy->n_addresses = 2; | 1800 | hw->wiphy->n_addresses = 2; |
1783 | hw->wiphy->addresses = data->addresses; | 1801 | hw->wiphy->addresses = data->addresses; |
1784 | 1802 | ||
1803 | hw->wiphy->iface_combinations = &hwsim_if_comb; | ||
1804 | hw->wiphy->n_iface_combinations = 1; | ||
1805 | |||
1785 | if (fake_hw_scan) { | 1806 | if (fake_hw_scan) { |
1786 | hw->wiphy->max_scan_ssids = 255; | 1807 | hw->wiphy->max_scan_ssids = 255; |
1787 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; | 1808 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 42c1af943111..510397b3d4a8 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -948,6 +948,19 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
948 | bss_cfg->ssid.ssid_len = params->ssid_len; | 948 | bss_cfg->ssid.ssid_len = params->ssid_len; |
949 | } | 949 | } |
950 | 950 | ||
951 | switch (params->hidden_ssid) { | ||
952 | case NL80211_HIDDEN_SSID_NOT_IN_USE: | ||
953 | bss_cfg->bcast_ssid_ctl = 1; | ||
954 | break; | ||
955 | case NL80211_HIDDEN_SSID_ZERO_LEN: | ||
956 | bss_cfg->bcast_ssid_ctl = 0; | ||
957 | break; | ||
958 | case NL80211_HIDDEN_SSID_ZERO_CONTENTS: | ||
959 | /* firmware doesn't support this type of hidden SSID */ | ||
960 | default: | ||
961 | return -EINVAL; | ||
962 | } | ||
963 | |||
951 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { | 964 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { |
952 | kfree(bss_cfg); | 965 | kfree(bss_cfg); |
953 | wiphy_err(wiphy, "Failed to parse secuirty parameters!\n"); | 966 | wiphy_err(wiphy, "Failed to parse secuirty parameters!\n"); |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 9f674bbebe65..561452a5c818 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -122,6 +122,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
122 | #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) | 122 | #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) |
123 | #define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44) | 123 | #define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44) |
124 | #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) | 124 | #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) |
125 | #define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48) | ||
125 | #define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) | 126 | #define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) |
126 | #define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) | 127 | #define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) |
127 | #define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) | 128 | #define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) |
@@ -1209,6 +1210,11 @@ struct host_cmd_tlv_ssid { | |||
1209 | u8 ssid[0]; | 1210 | u8 ssid[0]; |
1210 | } __packed; | 1211 | } __packed; |
1211 | 1212 | ||
1213 | struct host_cmd_tlv_bcast_ssid { | ||
1214 | struct host_cmd_tlv tlv; | ||
1215 | u8 bcast_ctl; | ||
1216 | } __packed; | ||
1217 | |||
1212 | struct host_cmd_tlv_beacon_period { | 1218 | struct host_cmd_tlv_beacon_period { |
1213 | struct host_cmd_tlv tlv; | 1219 | struct host_cmd_tlv tlv; |
1214 | __le16 period; | 1220 | __le16 period; |
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 76dfbc42a732..8173ab66066d 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -132,6 +132,7 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) | |||
132 | struct host_cmd_tlv_dtim_period *dtim_period; | 132 | struct host_cmd_tlv_dtim_period *dtim_period; |
133 | struct host_cmd_tlv_beacon_period *beacon_period; | 133 | struct host_cmd_tlv_beacon_period *beacon_period; |
134 | struct host_cmd_tlv_ssid *ssid; | 134 | struct host_cmd_tlv_ssid *ssid; |
135 | struct host_cmd_tlv_bcast_ssid *bcast_ssid; | ||
135 | struct host_cmd_tlv_channel_band *chan_band; | 136 | struct host_cmd_tlv_channel_band *chan_band; |
136 | struct host_cmd_tlv_frag_threshold *frag_threshold; | 137 | struct host_cmd_tlv_frag_threshold *frag_threshold; |
137 | struct host_cmd_tlv_rts_threshold *rts_threshold; | 138 | struct host_cmd_tlv_rts_threshold *rts_threshold; |
@@ -153,6 +154,14 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) | |||
153 | cmd_size += sizeof(struct host_cmd_tlv) + | 154 | cmd_size += sizeof(struct host_cmd_tlv) + |
154 | bss_cfg->ssid.ssid_len; | 155 | bss_cfg->ssid.ssid_len; |
155 | tlv += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len; | 156 | tlv += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len; |
157 | |||
158 | bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv; | ||
159 | bcast_ssid->tlv.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID); | ||
160 | bcast_ssid->tlv.len = | ||
161 | cpu_to_le16(sizeof(bcast_ssid->bcast_ctl)); | ||
162 | bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl; | ||
163 | cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid); | ||
164 | tlv += sizeof(struct host_cmd_tlv_bcast_ssid); | ||
156 | } | 165 | } |
157 | if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) { | 166 | if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) { |
158 | chan_band = (struct host_cmd_tlv_channel_band *)tlv; | 167 | chan_band = (struct host_cmd_tlv_channel_band *)tlv; |
@@ -416,6 +425,7 @@ int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel) | |||
416 | if (!bss_cfg) | 425 | if (!bss_cfg) |
417 | return -ENOMEM; | 426 | return -ENOMEM; |
418 | 427 | ||
428 | mwifiex_set_sys_config_invalid_data(bss_cfg); | ||
419 | bss_cfg->band_cfg = BAND_CONFIG_MANUAL; | 429 | bss_cfg->band_cfg = BAND_CONFIG_MANUAL; |
420 | bss_cfg->channel = channel; | 430 | bss_cfg->channel = channel; |
421 | 431 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index ca36cccaba31..8f754025b06e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -396,8 +396,7 @@ struct rt2x00_intf { | |||
396 | * for hardware which doesn't support hardware | 396 | * for hardware which doesn't support hardware |
397 | * sequence counting. | 397 | * sequence counting. |
398 | */ | 398 | */ |
399 | spinlock_t seqlock; | 399 | atomic_t seqno; |
400 | u16 seqno; | ||
401 | }; | 400 | }; |
402 | 401 | ||
403 | static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) | 402 | static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index b49773ef72f2..dd24b2663b5e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -277,7 +277,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
277 | else | 277 | else |
278 | rt2x00dev->intf_sta_count++; | 278 | rt2x00dev->intf_sta_count++; |
279 | 279 | ||
280 | spin_lock_init(&intf->seqlock); | ||
281 | mutex_init(&intf->beacon_skb_mutex); | 280 | mutex_init(&intf->beacon_skb_mutex); |
282 | intf->beacon = entry; | 281 | intf->beacon = entry; |
283 | 282 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 4c662eccf53c..2fd830103415 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -207,6 +207,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, | |||
207 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 207 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
208 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 208 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
209 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); | 209 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); |
210 | u16 seqno; | ||
210 | 211 | ||
211 | if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) | 212 | if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) |
212 | return; | 213 | return; |
@@ -238,15 +239,13 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, | |||
238 | * sequence counting per-frame, since those will override the | 239 | * sequence counting per-frame, since those will override the |
239 | * sequence counter given by mac80211. | 240 | * sequence counter given by mac80211. |
240 | */ | 241 | */ |
241 | spin_lock(&intf->seqlock); | ||
242 | |||
243 | if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) | 242 | if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) |
244 | intf->seqno += 0x10; | 243 | seqno = atomic_add_return(0x10, &intf->seqno); |
245 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | 244 | else |
246 | hdr->seq_ctrl |= cpu_to_le16(intf->seqno); | 245 | seqno = atomic_read(&intf->seqno); |
247 | |||
248 | spin_unlock(&intf->seqlock); | ||
249 | 246 | ||
247 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
248 | hdr->seq_ctrl |= cpu_to_le16(seqno); | ||
250 | } | 249 | } |
251 | 250 | ||
252 | static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev, | 251 | static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev, |
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index b94765e38e80..2040bff945d4 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h | |||
@@ -40,7 +40,10 @@ struct inet_peer { | |||
40 | u32 pmtu_orig; | 40 | u32 pmtu_orig; |
41 | u32 pmtu_learned; | 41 | u32 pmtu_learned; |
42 | struct inetpeer_addr_base redirect_learned; | 42 | struct inetpeer_addr_base redirect_learned; |
43 | struct list_head gc_list; | 43 | union { |
44 | struct list_head gc_list; | ||
45 | struct rcu_head gc_rcu; | ||
46 | }; | ||
44 | /* | 47 | /* |
45 | * Once inet_peer is queued for deletion (refcnt == -1), following fields | 48 | * Once inet_peer is queued for deletion (refcnt == -1), following fields |
46 | * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp | 49 | * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 46e7f86acfc9..3e18af4dadc4 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -210,7 +210,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) | |||
210 | } | 210 | } |
211 | 211 | ||
212 | if (sk->sk_state == BT_CONNECTED || !newsock || | 212 | if (sk->sk_state == BT_CONNECTED || !newsock || |
213 | test_bit(BT_DEFER_SETUP, &bt_sk(parent)->flags)) { | 213 | test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) { |
214 | bt_accept_unlink(sk); | 214 | bt_accept_unlink(sk); |
215 | if (newsock) | 215 | if (newsock) |
216 | sock_graft(sk, newsock); | 216 | sock_graft(sk, newsock); |
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index ea5fb9fcc3f5..d23b6682f4e9 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c | |||
@@ -36,9 +36,6 @@ | |||
36 | #define TRACE_ON 1 | 36 | #define TRACE_ON 1 |
37 | #define TRACE_OFF 0 | 37 | #define TRACE_OFF 0 |
38 | 38 | ||
39 | static void send_dm_alert(struct work_struct *unused); | ||
40 | |||
41 | |||
42 | /* | 39 | /* |
43 | * Globals, our netlink socket pointer | 40 | * Globals, our netlink socket pointer |
44 | * and the work handle that will send up | 41 | * and the work handle that will send up |
@@ -48,11 +45,10 @@ static int trace_state = TRACE_OFF; | |||
48 | static DEFINE_MUTEX(trace_state_mutex); | 45 | static DEFINE_MUTEX(trace_state_mutex); |
49 | 46 | ||
50 | struct per_cpu_dm_data { | 47 | struct per_cpu_dm_data { |
51 | struct work_struct dm_alert_work; | 48 | spinlock_t lock; |
52 | struct sk_buff __rcu *skb; | 49 | struct sk_buff *skb; |
53 | atomic_t dm_hit_count; | 50 | struct work_struct dm_alert_work; |
54 | struct timer_list send_timer; | 51 | struct timer_list send_timer; |
55 | int cpu; | ||
56 | }; | 52 | }; |
57 | 53 | ||
58 | struct dm_hw_stat_delta { | 54 | struct dm_hw_stat_delta { |
@@ -78,13 +74,13 @@ static int dm_delay = 1; | |||
78 | static unsigned long dm_hw_check_delta = 2*HZ; | 74 | static unsigned long dm_hw_check_delta = 2*HZ; |
79 | static LIST_HEAD(hw_stats_list); | 75 | static LIST_HEAD(hw_stats_list); |
80 | 76 | ||
81 | static void reset_per_cpu_data(struct per_cpu_dm_data *data) | 77 | static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data) |
82 | { | 78 | { |
83 | size_t al; | 79 | size_t al; |
84 | struct net_dm_alert_msg *msg; | 80 | struct net_dm_alert_msg *msg; |
85 | struct nlattr *nla; | 81 | struct nlattr *nla; |
86 | struct sk_buff *skb; | 82 | struct sk_buff *skb; |
87 | struct sk_buff *oskb = rcu_dereference_protected(data->skb, 1); | 83 | unsigned long flags; |
88 | 84 | ||
89 | al = sizeof(struct net_dm_alert_msg); | 85 | al = sizeof(struct net_dm_alert_msg); |
90 | al += dm_hit_limit * sizeof(struct net_dm_drop_point); | 86 | al += dm_hit_limit * sizeof(struct net_dm_drop_point); |
@@ -99,65 +95,40 @@ static void reset_per_cpu_data(struct per_cpu_dm_data *data) | |||
99 | sizeof(struct net_dm_alert_msg)); | 95 | sizeof(struct net_dm_alert_msg)); |
100 | msg = nla_data(nla); | 96 | msg = nla_data(nla); |
101 | memset(msg, 0, al); | 97 | memset(msg, 0, al); |
102 | } else | 98 | } else { |
103 | schedule_work_on(data->cpu, &data->dm_alert_work); | 99 | mod_timer(&data->send_timer, jiffies + HZ / 10); |
104 | |||
105 | /* | ||
106 | * Don't need to lock this, since we are guaranteed to only | ||
107 | * run this on a single cpu at a time. | ||
108 | * Note also that we only update data->skb if the old and new skb | ||
109 | * pointers don't match. This ensures that we don't continually call | ||
110 | * synchornize_rcu if we repeatedly fail to alloc a new netlink message. | ||
111 | */ | ||
112 | if (skb != oskb) { | ||
113 | rcu_assign_pointer(data->skb, skb); | ||
114 | |||
115 | synchronize_rcu(); | ||
116 | |||
117 | atomic_set(&data->dm_hit_count, dm_hit_limit); | ||
118 | } | 100 | } |
119 | 101 | ||
102 | spin_lock_irqsave(&data->lock, flags); | ||
103 | swap(data->skb, skb); | ||
104 | spin_unlock_irqrestore(&data->lock, flags); | ||
105 | |||
106 | return skb; | ||
120 | } | 107 | } |
121 | 108 | ||
122 | static void send_dm_alert(struct work_struct *unused) | 109 | static void send_dm_alert(struct work_struct *work) |
123 | { | 110 | { |
124 | struct sk_buff *skb; | 111 | struct sk_buff *skb; |
125 | struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data); | 112 | struct per_cpu_dm_data *data; |
126 | 113 | ||
127 | WARN_ON_ONCE(data->cpu != smp_processor_id()); | 114 | data = container_of(work, struct per_cpu_dm_data, dm_alert_work); |
128 | 115 | ||
129 | /* | 116 | skb = reset_per_cpu_data(data); |
130 | * Grab the skb we're about to send | ||
131 | */ | ||
132 | skb = rcu_dereference_protected(data->skb, 1); | ||
133 | |||
134 | /* | ||
135 | * Replace it with a new one | ||
136 | */ | ||
137 | reset_per_cpu_data(data); | ||
138 | 117 | ||
139 | /* | ||
140 | * Ship it! | ||
141 | */ | ||
142 | if (skb) | 118 | if (skb) |
143 | genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL); | 119 | genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL); |
144 | |||
145 | put_cpu_var(dm_cpu_data); | ||
146 | } | 120 | } |
147 | 121 | ||
148 | /* | 122 | /* |
149 | * This is the timer function to delay the sending of an alert | 123 | * This is the timer function to delay the sending of an alert |
150 | * in the event that more drops will arrive during the | 124 | * in the event that more drops will arrive during the |
151 | * hysteresis period. Note that it operates under the timer interrupt | 125 | * hysteresis period. |
152 | * so we don't need to disable preemption here | ||
153 | */ | 126 | */ |
154 | static void sched_send_work(unsigned long unused) | 127 | static void sched_send_work(unsigned long _data) |
155 | { | 128 | { |
156 | struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data); | 129 | struct per_cpu_dm_data *data = (struct per_cpu_dm_data *)_data; |
157 | |||
158 | schedule_work_on(smp_processor_id(), &data->dm_alert_work); | ||
159 | 130 | ||
160 | put_cpu_var(dm_cpu_data); | 131 | schedule_work(&data->dm_alert_work); |
161 | } | 132 | } |
162 | 133 | ||
163 | static void trace_drop_common(struct sk_buff *skb, void *location) | 134 | static void trace_drop_common(struct sk_buff *skb, void *location) |
@@ -167,33 +138,28 @@ static void trace_drop_common(struct sk_buff *skb, void *location) | |||
167 | struct nlattr *nla; | 138 | struct nlattr *nla; |
168 | int i; | 139 | int i; |
169 | struct sk_buff *dskb; | 140 | struct sk_buff *dskb; |
170 | struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data); | 141 | struct per_cpu_dm_data *data; |
171 | 142 | unsigned long flags; | |
172 | 143 | ||
173 | rcu_read_lock(); | 144 | local_irq_save(flags); |
174 | dskb = rcu_dereference(data->skb); | 145 | data = &__get_cpu_var(dm_cpu_data); |
146 | spin_lock(&data->lock); | ||
147 | dskb = data->skb; | ||
175 | 148 | ||
176 | if (!dskb) | 149 | if (!dskb) |
177 | goto out; | 150 | goto out; |
178 | 151 | ||
179 | if (!atomic_add_unless(&data->dm_hit_count, -1, 0)) { | ||
180 | /* | ||
181 | * we're already at zero, discard this hit | ||
182 | */ | ||
183 | goto out; | ||
184 | } | ||
185 | |||
186 | nlh = (struct nlmsghdr *)dskb->data; | 152 | nlh = (struct nlmsghdr *)dskb->data; |
187 | nla = genlmsg_data(nlmsg_data(nlh)); | 153 | nla = genlmsg_data(nlmsg_data(nlh)); |
188 | msg = nla_data(nla); | 154 | msg = nla_data(nla); |
189 | for (i = 0; i < msg->entries; i++) { | 155 | for (i = 0; i < msg->entries; i++) { |
190 | if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) { | 156 | if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) { |
191 | msg->points[i].count++; | 157 | msg->points[i].count++; |
192 | atomic_inc(&data->dm_hit_count); | ||
193 | goto out; | 158 | goto out; |
194 | } | 159 | } |
195 | } | 160 | } |
196 | 161 | if (msg->entries == dm_hit_limit) | |
162 | goto out; | ||
197 | /* | 163 | /* |
198 | * We need to create a new entry | 164 | * We need to create a new entry |
199 | */ | 165 | */ |
@@ -205,13 +171,11 @@ static void trace_drop_common(struct sk_buff *skb, void *location) | |||
205 | 171 | ||
206 | if (!timer_pending(&data->send_timer)) { | 172 | if (!timer_pending(&data->send_timer)) { |
207 | data->send_timer.expires = jiffies + dm_delay * HZ; | 173 | data->send_timer.expires = jiffies + dm_delay * HZ; |
208 | add_timer_on(&data->send_timer, smp_processor_id()); | 174 | add_timer(&data->send_timer); |
209 | } | 175 | } |
210 | 176 | ||
211 | out: | 177 | out: |
212 | rcu_read_unlock(); | 178 | spin_unlock_irqrestore(&data->lock, flags); |
213 | put_cpu_var(dm_cpu_data); | ||
214 | return; | ||
215 | } | 179 | } |
216 | 180 | ||
217 | static void trace_kfree_skb_hit(void *ignore, struct sk_buff *skb, void *location) | 181 | static void trace_kfree_skb_hit(void *ignore, struct sk_buff *skb, void *location) |
@@ -418,11 +382,11 @@ static int __init init_net_drop_monitor(void) | |||
418 | 382 | ||
419 | for_each_possible_cpu(cpu) { | 383 | for_each_possible_cpu(cpu) { |
420 | data = &per_cpu(dm_cpu_data, cpu); | 384 | data = &per_cpu(dm_cpu_data, cpu); |
421 | data->cpu = cpu; | ||
422 | INIT_WORK(&data->dm_alert_work, send_dm_alert); | 385 | INIT_WORK(&data->dm_alert_work, send_dm_alert); |
423 | init_timer(&data->send_timer); | 386 | init_timer(&data->send_timer); |
424 | data->send_timer.data = cpu; | 387 | data->send_timer.data = (unsigned long)data; |
425 | data->send_timer.function = sched_send_work; | 388 | data->send_timer.function = sched_send_work; |
389 | spin_lock_init(&data->lock); | ||
426 | reset_per_cpu_data(data); | 390 | reset_per_cpu_data(data); |
427 | } | 391 | } |
428 | 392 | ||
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index d4d61b694fab..dfba343b2509 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c | |||
@@ -560,6 +560,17 @@ bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout) | |||
560 | } | 560 | } |
561 | EXPORT_SYMBOL(inet_peer_xrlim_allow); | 561 | EXPORT_SYMBOL(inet_peer_xrlim_allow); |
562 | 562 | ||
563 | static void inetpeer_inval_rcu(struct rcu_head *head) | ||
564 | { | ||
565 | struct inet_peer *p = container_of(head, struct inet_peer, gc_rcu); | ||
566 | |||
567 | spin_lock_bh(&gc_lock); | ||
568 | list_add_tail(&p->gc_list, &gc_list); | ||
569 | spin_unlock_bh(&gc_lock); | ||
570 | |||
571 | schedule_delayed_work(&gc_work, gc_delay); | ||
572 | } | ||
573 | |||
563 | void inetpeer_invalidate_tree(int family) | 574 | void inetpeer_invalidate_tree(int family) |
564 | { | 575 | { |
565 | struct inet_peer *old, *new, *prev; | 576 | struct inet_peer *old, *new, *prev; |
@@ -576,10 +587,7 @@ void inetpeer_invalidate_tree(int family) | |||
576 | prev = cmpxchg(&base->root, old, new); | 587 | prev = cmpxchg(&base->root, old, new); |
577 | if (prev == old) { | 588 | if (prev == old) { |
578 | base->total = 0; | 589 | base->total = 0; |
579 | spin_lock(&gc_lock); | 590 | call_rcu(&prev->gc_rcu, inetpeer_inval_rcu); |
580 | list_add_tail(&prev->gc_list, &gc_list); | ||
581 | spin_unlock(&gc_lock); | ||
582 | schedule_delayed_work(&gc_work, gc_delay); | ||
583 | } | 591 | } |
584 | 592 | ||
585 | out: | 593 | out: |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 26ddb699d693..c649188314cc 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -145,15 +145,20 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
145 | struct tid_ampdu_rx *tid_rx; | 145 | struct tid_ampdu_rx *tid_rx; |
146 | unsigned long timeout; | 146 | unsigned long timeout; |
147 | 147 | ||
148 | rcu_read_lock(); | ||
148 | tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]); | 149 | tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]); |
149 | if (!tid_rx) | 150 | if (!tid_rx) { |
151 | rcu_read_unlock(); | ||
150 | return; | 152 | return; |
153 | } | ||
151 | 154 | ||
152 | timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout); | 155 | timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout); |
153 | if (time_is_after_jiffies(timeout)) { | 156 | if (time_is_after_jiffies(timeout)) { |
154 | mod_timer(&tid_rx->session_timer, timeout); | 157 | mod_timer(&tid_rx->session_timer, timeout); |
158 | rcu_read_unlock(); | ||
155 | return; | 159 | return; |
156 | } | 160 | } |
161 | rcu_read_unlock(); | ||
157 | 162 | ||
158 | #ifdef CONFIG_MAC80211_HT_DEBUG | 163 | #ifdef CONFIG_MAC80211_HT_DEBUG |
159 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 164 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 495831ee48f1..e9cecca5c44d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -533,16 +533,16 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, | |||
533 | sinfo.filled = 0; | 533 | sinfo.filled = 0; |
534 | sta_set_sinfo(sta, &sinfo); | 534 | sta_set_sinfo(sta, &sinfo); |
535 | 535 | ||
536 | if (sinfo.filled | STATION_INFO_TX_BITRATE) | 536 | if (sinfo.filled & STATION_INFO_TX_BITRATE) |
537 | data[i] = 100000 * | 537 | data[i] = 100000 * |
538 | cfg80211_calculate_bitrate(&sinfo.txrate); | 538 | cfg80211_calculate_bitrate(&sinfo.txrate); |
539 | i++; | 539 | i++; |
540 | if (sinfo.filled | STATION_INFO_RX_BITRATE) | 540 | if (sinfo.filled & STATION_INFO_RX_BITRATE) |
541 | data[i] = 100000 * | 541 | data[i] = 100000 * |
542 | cfg80211_calculate_bitrate(&sinfo.rxrate); | 542 | cfg80211_calculate_bitrate(&sinfo.rxrate); |
543 | i++; | 543 | i++; |
544 | 544 | ||
545 | if (sinfo.filled | STATION_INFO_SIGNAL_AVG) | 545 | if (sinfo.filled & STATION_INFO_SIGNAL_AVG) |
546 | data[i] = (u8)sinfo.signal_avg; | 546 | data[i] = (u8)sinfo.signal_avg; |
547 | i++; | 547 | i++; |
548 | } else { | 548 | } else { |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d4c19a7773db..8664111d0566 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -637,6 +637,18 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
637 | ieee80211_configure_filter(local); | 637 | ieee80211_configure_filter(local); |
638 | break; | 638 | break; |
639 | default: | 639 | default: |
640 | mutex_lock(&local->mtx); | ||
641 | if (local->hw_roc_dev == sdata->dev && | ||
642 | local->hw_roc_channel) { | ||
643 | /* ignore return value since this is racy */ | ||
644 | drv_cancel_remain_on_channel(local); | ||
645 | ieee80211_queue_work(&local->hw, &local->hw_roc_done); | ||
646 | } | ||
647 | mutex_unlock(&local->mtx); | ||
648 | |||
649 | flush_work(&local->hw_roc_start); | ||
650 | flush_work(&local->hw_roc_done); | ||
651 | |||
640 | flush_work(&sdata->work); | 652 | flush_work(&sdata->work); |
641 | /* | 653 | /* |
642 | * When we get here, the interface is marked down. | 654 | * When we get here, the interface is marked down. |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 04c306308987..d94627c2929c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1220,6 +1220,22 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1220 | sdata->vif.bss_conf.qos = true; | 1220 | sdata->vif.bss_conf.qos = true; |
1221 | } | 1221 | } |
1222 | 1222 | ||
1223 | static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) | ||
1224 | { | ||
1225 | lockdep_assert_held(&sdata->local->mtx); | ||
1226 | |||
1227 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
1228 | IEEE80211_STA_BEACON_POLL); | ||
1229 | ieee80211_run_deferred_scan(sdata->local); | ||
1230 | } | ||
1231 | |||
1232 | static void ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) | ||
1233 | { | ||
1234 | mutex_lock(&sdata->local->mtx); | ||
1235 | __ieee80211_stop_poll(sdata); | ||
1236 | mutex_unlock(&sdata->local->mtx); | ||
1237 | } | ||
1238 | |||
1223 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | 1239 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, |
1224 | u16 capab, bool erp_valid, u8 erp) | 1240 | u16 capab, bool erp_valid, u8 erp) |
1225 | { | 1241 | { |
@@ -1285,8 +1301,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1285 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; | 1301 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; |
1286 | 1302 | ||
1287 | /* just to be sure */ | 1303 | /* just to be sure */ |
1288 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 1304 | ieee80211_stop_poll(sdata); |
1289 | IEEE80211_STA_BEACON_POLL); | ||
1290 | 1305 | ||
1291 | ieee80211_led_assoc(local, 1); | 1306 | ieee80211_led_assoc(local, 1); |
1292 | 1307 | ||
@@ -1456,8 +1471,7 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) | |||
1456 | return; | 1471 | return; |
1457 | } | 1472 | } |
1458 | 1473 | ||
1459 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 1474 | __ieee80211_stop_poll(sdata); |
1460 | IEEE80211_STA_BEACON_POLL); | ||
1461 | 1475 | ||
1462 | mutex_lock(&local->iflist_mtx); | 1476 | mutex_lock(&local->iflist_mtx); |
1463 | ieee80211_recalc_ps(local, -1); | 1477 | ieee80211_recalc_ps(local, -1); |
@@ -1477,7 +1491,6 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) | |||
1477 | round_jiffies_up(jiffies + | 1491 | round_jiffies_up(jiffies + |
1478 | IEEE80211_CONNECTION_IDLE_TIME)); | 1492 | IEEE80211_CONNECTION_IDLE_TIME)); |
1479 | out: | 1493 | out: |
1480 | ieee80211_run_deferred_scan(local); | ||
1481 | mutex_unlock(&local->mtx); | 1494 | mutex_unlock(&local->mtx); |
1482 | } | 1495 | } |
1483 | 1496 | ||
@@ -2408,7 +2421,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2408 | net_dbg_ratelimited("%s: cancelling probereq poll due to a received beacon\n", | 2421 | net_dbg_ratelimited("%s: cancelling probereq poll due to a received beacon\n", |
2409 | sdata->name); | 2422 | sdata->name); |
2410 | #endif | 2423 | #endif |
2424 | mutex_lock(&local->mtx); | ||
2411 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; | 2425 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; |
2426 | ieee80211_run_deferred_scan(local); | ||
2427 | mutex_unlock(&local->mtx); | ||
2428 | |||
2412 | mutex_lock(&local->iflist_mtx); | 2429 | mutex_lock(&local->iflist_mtx); |
2413 | ieee80211_recalc_ps(local, -1); | 2430 | ieee80211_recalc_ps(local, -1); |
2414 | mutex_unlock(&local->iflist_mtx); | 2431 | mutex_unlock(&local->iflist_mtx); |
@@ -2595,8 +2612,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |||
2595 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2612 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2596 | u8 frame_buf[DEAUTH_DISASSOC_LEN]; | 2613 | u8 frame_buf[DEAUTH_DISASSOC_LEN]; |
2597 | 2614 | ||
2598 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 2615 | ieee80211_stop_poll(sdata); |
2599 | IEEE80211_STA_BEACON_POLL); | ||
2600 | 2616 | ||
2601 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, | 2617 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, |
2602 | false, frame_buf); | 2618 | false, frame_buf); |
@@ -2874,8 +2890,7 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | |||
2874 | u32 flags; | 2890 | u32 flags; |
2875 | 2891 | ||
2876 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 2892 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
2877 | sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL | | 2893 | __ieee80211_stop_poll(sdata); |
2878 | IEEE80211_STA_CONNECTION_POLL); | ||
2879 | 2894 | ||
2880 | /* let's probe the connection once */ | 2895 | /* let's probe the connection once */ |
2881 | flags = sdata->local->hw.flags; | 2896 | flags = sdata->local->hw.flags; |
@@ -2944,7 +2959,10 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | |||
2944 | if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) | 2959 | if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) |
2945 | add_timer(&ifmgd->chswitch_timer); | 2960 | add_timer(&ifmgd->chswitch_timer); |
2946 | ieee80211_sta_reset_beacon_monitor(sdata); | 2961 | ieee80211_sta_reset_beacon_monitor(sdata); |
2962 | |||
2963 | mutex_lock(&sdata->local->mtx); | ||
2947 | ieee80211_restart_sta_timer(sdata); | 2964 | ieee80211_restart_sta_timer(sdata); |
2965 | mutex_unlock(&sdata->local->mtx); | ||
2948 | } | 2966 | } |
2949 | #endif | 2967 | #endif |
2950 | 2968 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index f054e94901a2..935aa4b6deee 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -234,6 +234,22 @@ static void ieee80211_hw_roc_done(struct work_struct *work) | |||
234 | return; | 234 | return; |
235 | } | 235 | } |
236 | 236 | ||
237 | /* was never transmitted */ | ||
238 | if (local->hw_roc_skb) { | ||
239 | u64 cookie; | ||
240 | |||
241 | cookie = local->hw_roc_cookie ^ 2; | ||
242 | |||
243 | cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie, | ||
244 | local->hw_roc_skb->data, | ||
245 | local->hw_roc_skb->len, false, | ||
246 | GFP_KERNEL); | ||
247 | |||
248 | kfree_skb(local->hw_roc_skb); | ||
249 | local->hw_roc_skb = NULL; | ||
250 | local->hw_roc_skb_for_status = NULL; | ||
251 | } | ||
252 | |||
237 | if (!local->hw_roc_for_tx) | 253 | if (!local->hw_roc_for_tx) |
238 | cfg80211_remain_on_channel_expired(local->hw_roc_dev, | 254 | cfg80211_remain_on_channel_expired(local->hw_roc_dev, |
239 | local->hw_roc_cookie, | 255 | local->hw_roc_cookie, |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f5b1638fbf80..de455f8bbb91 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -378,7 +378,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
378 | /* make the station visible */ | 378 | /* make the station visible */ |
379 | sta_info_hash_add(local, sta); | 379 | sta_info_hash_add(local, sta); |
380 | 380 | ||
381 | list_add(&sta->list, &local->sta_list); | 381 | list_add_rcu(&sta->list, &local->sta_list); |
382 | 382 | ||
383 | set_sta_flag(sta, WLAN_STA_INSERTED); | 383 | set_sta_flag(sta, WLAN_STA_INSERTED); |
384 | 384 | ||
@@ -688,7 +688,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
688 | if (ret) | 688 | if (ret) |
689 | return ret; | 689 | return ret; |
690 | 690 | ||
691 | list_del(&sta->list); | 691 | list_del_rcu(&sta->list); |
692 | 692 | ||
693 | mutex_lock(&local->key_mtx); | 693 | mutex_lock(&local->key_mtx); |
694 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) | 694 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 847215bb2a6f..e453212fa17f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1737,7 +1737,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1737 | __le16 fc; | 1737 | __le16 fc; |
1738 | struct ieee80211_hdr hdr; | 1738 | struct ieee80211_hdr hdr; |
1739 | struct ieee80211s_hdr mesh_hdr __maybe_unused; | 1739 | struct ieee80211s_hdr mesh_hdr __maybe_unused; |
1740 | struct mesh_path __maybe_unused *mppath = NULL; | 1740 | struct mesh_path __maybe_unused *mppath = NULL, *mpath = NULL; |
1741 | const u8 *encaps_data; | 1741 | const u8 *encaps_data; |
1742 | int encaps_len, skip_header_bytes; | 1742 | int encaps_len, skip_header_bytes; |
1743 | int nh_pos, h_pos; | 1743 | int nh_pos, h_pos; |
@@ -1803,8 +1803,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1803 | goto fail; | 1803 | goto fail; |
1804 | } | 1804 | } |
1805 | rcu_read_lock(); | 1805 | rcu_read_lock(); |
1806 | if (!is_multicast_ether_addr(skb->data)) | 1806 | if (!is_multicast_ether_addr(skb->data)) { |
1807 | mppath = mpp_path_lookup(skb->data, sdata); | 1807 | mpath = mesh_path_lookup(skb->data, sdata); |
1808 | if (!mpath) | ||
1809 | mppath = mpp_path_lookup(skb->data, sdata); | ||
1810 | } | ||
1808 | 1811 | ||
1809 | /* | 1812 | /* |
1810 | * Use address extension if it is a packet from | 1813 | * Use address extension if it is a packet from |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index a44c6807df01..8dd4712620ff 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1271,7 +1271,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1271 | enum ieee80211_sta_state state; | 1271 | enum ieee80211_sta_state state; |
1272 | 1272 | ||
1273 | for (state = IEEE80211_STA_NOTEXIST; | 1273 | for (state = IEEE80211_STA_NOTEXIST; |
1274 | state < sta->sta_state - 1; state++) | 1274 | state < sta->sta_state; state++) |
1275 | WARN_ON(drv_sta_state(local, sta->sdata, sta, | 1275 | WARN_ON(drv_sta_state(local, sta->sdata, sta, |
1276 | state, state + 1)); | 1276 | state, state + 1)); |
1277 | } | 1277 | } |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index d2a19b0ff71f..89baa3328411 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -42,6 +42,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) | |||
42 | cfg80211_hold_bss(bss_from_pub(bss)); | 42 | cfg80211_hold_bss(bss_from_pub(bss)); |
43 | wdev->current_bss = bss_from_pub(bss); | 43 | wdev->current_bss = bss_from_pub(bss); |
44 | 44 | ||
45 | wdev->sme_state = CFG80211_SME_CONNECTED; | ||
45 | cfg80211_upload_connect_keys(wdev); | 46 | cfg80211_upload_connect_keys(wdev); |
46 | 47 | ||
47 | nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, | 48 | nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, |
@@ -60,7 +61,7 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) | |||
60 | struct cfg80211_event *ev; | 61 | struct cfg80211_event *ev; |
61 | unsigned long flags; | 62 | unsigned long flags; |
62 | 63 | ||
63 | CFG80211_DEV_WARN_ON(!wdev->ssid_len); | 64 | CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING); |
64 | 65 | ||
65 | ev = kzalloc(sizeof(*ev), gfp); | 66 | ev = kzalloc(sizeof(*ev), gfp); |
66 | if (!ev) | 67 | if (!ev) |
@@ -115,9 +116,11 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
115 | #ifdef CONFIG_CFG80211_WEXT | 116 | #ifdef CONFIG_CFG80211_WEXT |
116 | wdev->wext.ibss.channel = params->channel; | 117 | wdev->wext.ibss.channel = params->channel; |
117 | #endif | 118 | #endif |
119 | wdev->sme_state = CFG80211_SME_CONNECTING; | ||
118 | err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); | 120 | err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); |
119 | if (err) { | 121 | if (err) { |
120 | wdev->connect_keys = NULL; | 122 | wdev->connect_keys = NULL; |
123 | wdev->sme_state = CFG80211_SME_IDLE; | ||
121 | return err; | 124 | return err; |
122 | } | 125 | } |
123 | 126 | ||
@@ -169,6 +172,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) | |||
169 | } | 172 | } |
170 | 173 | ||
171 | wdev->current_bss = NULL; | 174 | wdev->current_bss = NULL; |
175 | wdev->sme_state = CFG80211_SME_IDLE; | ||
172 | wdev->ssid_len = 0; | 176 | wdev->ssid_len = 0; |
173 | #ifdef CONFIG_CFG80211_WEXT | 177 | #ifdef CONFIG_CFG80211_WEXT |
174 | if (!nowext) | 178 | if (!nowext) |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 55d99466babb..8f2d68fc3a44 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -935,6 +935,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
935 | enum nl80211_iftype iftype) | 935 | enum nl80211_iftype iftype) |
936 | { | 936 | { |
937 | struct wireless_dev *wdev_iter; | 937 | struct wireless_dev *wdev_iter; |
938 | u32 used_iftypes = BIT(iftype); | ||
938 | int num[NUM_NL80211_IFTYPES]; | 939 | int num[NUM_NL80211_IFTYPES]; |
939 | int total = 1; | 940 | int total = 1; |
940 | int i, j; | 941 | int i, j; |
@@ -961,6 +962,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
961 | 962 | ||
962 | num[wdev_iter->iftype]++; | 963 | num[wdev_iter->iftype]++; |
963 | total++; | 964 | total++; |
965 | used_iftypes |= BIT(wdev_iter->iftype); | ||
964 | } | 966 | } |
965 | mutex_unlock(&rdev->devlist_mtx); | 967 | mutex_unlock(&rdev->devlist_mtx); |
966 | 968 | ||
@@ -970,6 +972,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
970 | for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { | 972 | for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { |
971 | const struct ieee80211_iface_combination *c; | 973 | const struct ieee80211_iface_combination *c; |
972 | struct ieee80211_iface_limit *limits; | 974 | struct ieee80211_iface_limit *limits; |
975 | u32 all_iftypes = 0; | ||
973 | 976 | ||
974 | c = &rdev->wiphy.iface_combinations[i]; | 977 | c = &rdev->wiphy.iface_combinations[i]; |
975 | 978 | ||
@@ -984,6 +987,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
984 | if (rdev->wiphy.software_iftypes & BIT(iftype)) | 987 | if (rdev->wiphy.software_iftypes & BIT(iftype)) |
985 | continue; | 988 | continue; |
986 | for (j = 0; j < c->n_limits; j++) { | 989 | for (j = 0; j < c->n_limits; j++) { |
990 | all_iftypes |= limits[j].types; | ||
987 | if (!(limits[j].types & BIT(iftype))) | 991 | if (!(limits[j].types & BIT(iftype))) |
988 | continue; | 992 | continue; |
989 | if (limits[j].max < num[iftype]) | 993 | if (limits[j].max < num[iftype]) |
@@ -991,7 +995,20 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
991 | limits[j].max -= num[iftype]; | 995 | limits[j].max -= num[iftype]; |
992 | } | 996 | } |
993 | } | 997 | } |
994 | /* yay, it fits */ | 998 | |
999 | /* | ||
1000 | * Finally check that all iftypes that we're currently | ||
1001 | * using are actually part of this combination. If they | ||
1002 | * aren't then we can't use this combination and have | ||
1003 | * to continue to the next. | ||
1004 | */ | ||
1005 | if ((all_iftypes & used_iftypes) != used_iftypes) | ||
1006 | goto cont; | ||
1007 | |||
1008 | /* | ||
1009 | * This combination covered all interface types and | ||
1010 | * supported the requested numbers, so we're good. | ||
1011 | */ | ||
995 | kfree(limits); | 1012 | kfree(limits); |
996 | return 0; | 1013 | return 0; |
997 | cont: | 1014 | cont: |