Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
This commit is contained in:
commit
c1864cfb80
@ -10,8 +10,8 @@ Currently this network device driver is for all STM embedded MAC/GMAC
|
|||||||
(i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000
|
(i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000
|
||||||
FF1152AMT0221 D1215994A VIRTEX FPGA board.
|
FF1152AMT0221 D1215994A VIRTEX FPGA board.
|
||||||
|
|
||||||
DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether MAC 10/100
|
DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether
|
||||||
Universal version 4.0 have been used for developing this driver.
|
MAC 10/100 Universal version 4.0 have been used for developing this driver.
|
||||||
|
|
||||||
This driver supports both the platform bus and PCI.
|
This driver supports both the platform bus and PCI.
|
||||||
|
|
||||||
@ -54,27 +54,27 @@ net_device structure enabling the scatter/gather feature.
|
|||||||
When one or more packets are received, an interrupt happens. The interrupts
|
When one or more packets are received, an interrupt happens. The interrupts
|
||||||
are not queued so the driver has to scan all the descriptors in the ring during
|
are not queued so the driver has to scan all the descriptors in the ring during
|
||||||
the receive process.
|
the receive process.
|
||||||
This is based on NAPI so the interrupt handler signals only if there is work to be
|
This is based on NAPI so the interrupt handler signals only if there is work
|
||||||
done, and it exits.
|
to be done, and it exits.
|
||||||
Then the poll method will be scheduled at some future point.
|
Then the poll method will be scheduled at some future point.
|
||||||
The incoming packets are stored, by the DMA, in a list of pre-allocated socket
|
The incoming packets are stored, by the DMA, in a list of pre-allocated socket
|
||||||
buffers in order to avoid the memcpy (Zero-copy).
|
buffers in order to avoid the memcpy (Zero-copy).
|
||||||
|
|
||||||
4.3) Timer-Driver Interrupt
|
4.3) Timer-Driver Interrupt
|
||||||
Instead of having the device that asynchronously notifies the frame receptions, the
|
Instead of having the device that asynchronously notifies the frame receptions,
|
||||||
driver configures a timer to generate an interrupt at regular intervals.
|
the driver configures a timer to generate an interrupt at regular intervals.
|
||||||
Based on the granularity of the timer, the frames that are received by the device
|
Based on the granularity of the timer, the frames that are received by the
|
||||||
will experience different levels of latency. Some NICs have dedicated timer
|
device will experience different levels of latency. Some NICs have dedicated
|
||||||
device to perform this task. STMMAC can use either the RTC device or the TMU
|
timer device to perform this task. STMMAC can use either the RTC device or the
|
||||||
channel 2 on STLinux platforms.
|
TMU channel 2 on STLinux platforms.
|
||||||
The timers frequency can be passed to the driver as parameter; when change it,
|
The timers frequency can be passed to the driver as parameter; when change it,
|
||||||
take care of both hardware capability and network stability/performance impact.
|
take care of both hardware capability and network stability/performance impact.
|
||||||
Several performance tests on STM platforms showed this optimisation allows to spare
|
Several performance tests on STM platforms showed this optimisation allows to
|
||||||
the CPU while having the maximum throughput.
|
spare the CPU while having the maximum throughput.
|
||||||
|
|
||||||
4.4) WOL
|
4.4) WOL
|
||||||
Wake up on Lan feature through Magic and Unicast frames are supported for the GMAC
|
Wake up on Lan feature through Magic and Unicast frames are supported for the
|
||||||
core.
|
GMAC core.
|
||||||
|
|
||||||
4.5) DMA descriptors
|
4.5) DMA descriptors
|
||||||
Driver handles both normal and enhanced descriptors. The latter has been only
|
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
|
|||||||
These are included in the include/linux/stmmac.h header file
|
These are included in the include/linux/stmmac.h header file
|
||||||
and detailed below as well:
|
and detailed below as well:
|
||||||
|
|
||||||
struct plat_stmmacenet_data {
|
struct plat_stmmacenet_data {
|
||||||
|
char *phy_bus_name;
|
||||||
int bus_id;
|
int bus_id;
|
||||||
int phy_addr;
|
int phy_addr;
|
||||||
int interface;
|
int interface;
|
||||||
@ -124,19 +125,24 @@ and detailed below as well:
|
|||||||
void (*bus_setup)(void __iomem *ioaddr);
|
void (*bus_setup)(void __iomem *ioaddr);
|
||||||
int (*init)(struct platform_device *pdev);
|
int (*init)(struct platform_device *pdev);
|
||||||
void (*exit)(struct platform_device *pdev);
|
void (*exit)(struct platform_device *pdev);
|
||||||
|
void *custom_cfg;
|
||||||
|
void *custom_data;
|
||||||
void *bsp_priv;
|
void *bsp_priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
Where:
|
Where:
|
||||||
|
o phy_bus_name: phy bus name to attach to the stmmac.
|
||||||
o bus_id: bus identifier.
|
o bus_id: bus identifier.
|
||||||
o phy_addr: the physical address can be passed from the platform.
|
o phy_addr: the physical address can be passed from the platform.
|
||||||
If it is set to -1 the driver will automatically
|
If it is set to -1 the driver will automatically
|
||||||
detect it at run-time by probing all the 32 addresses.
|
detect it at run-time by probing all the 32 addresses.
|
||||||
o interface: PHY device's interface.
|
o interface: PHY device's interface.
|
||||||
o mdio_bus_data: specific platform fields for the MDIO bus.
|
o mdio_bus_data: specific platform fields for the MDIO bus.
|
||||||
o pbl: the Programmable Burst Length is maximum number of beats to
|
o dma_cfg: internal DMA parameters
|
||||||
|
o pbl: the Programmable Burst Length is maximum number of beats to
|
||||||
be transferred in one DMA transaction.
|
be transferred in one DMA transaction.
|
||||||
GMAC also enables the 4xPBL by default.
|
GMAC also enables the 4xPBL by default.
|
||||||
|
o fixed_burst/mixed_burst/burst_len
|
||||||
o clk_csr: fixed CSR Clock range selection.
|
o clk_csr: fixed CSR Clock range selection.
|
||||||
o has_gmac: uses the GMAC core.
|
o has_gmac: uses the GMAC core.
|
||||||
o enh_desc: if sets the MAC will use the enhanced descriptor structure.
|
o enh_desc: if sets the MAC will use the enhanced descriptor structure.
|
||||||
@ -160,8 +166,9 @@ Where:
|
|||||||
this is sometime necessary on some platforms (e.g. ST boxes)
|
this is sometime necessary on some platforms (e.g. ST boxes)
|
||||||
where the HW needs to have set some PIO lines or system cfg
|
where the HW needs to have set some PIO lines or system cfg
|
||||||
registers.
|
registers.
|
||||||
o custom_cfg: this is a custom configuration that can be passed while
|
o custom_cfg/custom_data: this is a custom configuration that can be passed
|
||||||
initialising the resources.
|
while initialising the resources.
|
||||||
|
o bsp_priv: another private poiter.
|
||||||
|
|
||||||
For MDIO bus The we have:
|
For MDIO bus The we have:
|
||||||
|
|
||||||
@ -180,7 +187,6 @@ Where:
|
|||||||
o irqs: list of IRQs, one per PHY.
|
o irqs: list of IRQs, one per PHY.
|
||||||
o probed_phy_irq: if irqs is NULL, use this for probed PHY.
|
o probed_phy_irq: if irqs is NULL, use this for probed PHY.
|
||||||
|
|
||||||
|
|
||||||
For DMA engine we have the following internal fields that should be
|
For DMA engine we have the following internal fields that should be
|
||||||
tuned according to the HW capabilities.
|
tuned according to the HW capabilities.
|
||||||
|
|
||||||
|
@ -139,7 +139,9 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
|||||||
bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
|
bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
|
||||||
break;
|
break;
|
||||||
case 0x4331:
|
case 0x4331:
|
||||||
/* BCM4331 workaround is SPROM-related, we put it in sprom.c */
|
case 43431:
|
||||||
|
/* Ext PA lines must be enabled for tx on BCM4331 */
|
||||||
|
bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true);
|
||||||
break;
|
break;
|
||||||
case 43224:
|
case 43224:
|
||||||
if (bus->chipinfo.rev == 0) {
|
if (bus->chipinfo.rev == 0) {
|
||||||
|
@ -579,13 +579,13 @@ int bcma_sprom_get(struct bcma_bus *bus)
|
|||||||
if (!sprom)
|
if (!sprom)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (bus->chipinfo.id == 0x4331)
|
if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431)
|
||||||
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
|
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
|
||||||
|
|
||||||
pr_debug("SPROM offset 0x%x\n", offset);
|
pr_debug("SPROM offset 0x%x\n", offset);
|
||||||
bcma_sprom_read(bus, offset, sprom);
|
bcma_sprom_read(bus, offset, sprom);
|
||||||
|
|
||||||
if (bus->chipinfo.id == 0x4331)
|
if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431)
|
||||||
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
|
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
|
||||||
|
|
||||||
err = bcma_sprom_valid(sprom);
|
err = bcma_sprom_valid(sprom);
|
||||||
|
@ -686,7 +686,7 @@ static int c_can_get_berr_counter(const struct net_device *dev,
|
|||||||
*
|
*
|
||||||
* We iterate from priv->tx_echo to priv->tx_next and check if the
|
* We iterate from priv->tx_echo to priv->tx_next and check if the
|
||||||
* packet has been transmitted, echo it back to the CAN framework.
|
* packet has been transmitted, echo it back to the CAN framework.
|
||||||
* If we discover a not yet transmitted package, stop looking for more.
|
* If we discover a not yet transmitted packet, stop looking for more.
|
||||||
*/
|
*/
|
||||||
static void c_can_do_tx(struct net_device *dev)
|
static void c_can_do_tx(struct net_device *dev)
|
||||||
{
|
{
|
||||||
@ -698,7 +698,7 @@ static void c_can_do_tx(struct net_device *dev)
|
|||||||
for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
|
for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
|
||||||
msg_obj_no = get_tx_echo_msg_obj(priv);
|
msg_obj_no = get_tx_echo_msg_obj(priv);
|
||||||
val = c_can_read_reg32(priv, &priv->regs->txrqst1);
|
val = c_can_read_reg32(priv, &priv->regs->txrqst1);
|
||||||
if (!(val & (1 << msg_obj_no))) {
|
if (!(val & (1 << (msg_obj_no - 1)))) {
|
||||||
can_get_echo_skb(dev,
|
can_get_echo_skb(dev,
|
||||||
msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
|
msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
|
||||||
stats->tx_bytes += priv->read_reg(priv,
|
stats->tx_bytes += priv->read_reg(priv,
|
||||||
@ -706,6 +706,8 @@ static void c_can_do_tx(struct net_device *dev)
|
|||||||
& IF_MCONT_DLC_MASK;
|
& IF_MCONT_DLC_MASK;
|
||||||
stats->tx_packets++;
|
stats->tx_packets++;
|
||||||
c_can_inval_msg_object(dev, 0, msg_obj_no);
|
c_can_inval_msg_object(dev, 0, msg_obj_no);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -950,7 +952,7 @@ static int c_can_poll(struct napi_struct *napi, int quota)
|
|||||||
struct net_device *dev = napi->dev;
|
struct net_device *dev = napi->dev;
|
||||||
struct c_can_priv *priv = netdev_priv(dev);
|
struct c_can_priv *priv = netdev_priv(dev);
|
||||||
|
|
||||||
irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
|
irqstatus = priv->irqstatus;
|
||||||
if (!irqstatus)
|
if (!irqstatus)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
@ -1028,12 +1030,11 @@ end:
|
|||||||
|
|
||||||
static irqreturn_t c_can_isr(int irq, void *dev_id)
|
static irqreturn_t c_can_isr(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
u16 irqstatus;
|
|
||||||
struct net_device *dev = (struct net_device *)dev_id;
|
struct net_device *dev = (struct net_device *)dev_id;
|
||||||
struct c_can_priv *priv = netdev_priv(dev);
|
struct c_can_priv *priv = netdev_priv(dev);
|
||||||
|
|
||||||
irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
|
priv->irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
|
||||||
if (!irqstatus)
|
if (!priv->irqstatus)
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
/* disable all interrupts and schedule the NAPI */
|
/* disable all interrupts and schedule the NAPI */
|
||||||
@ -1063,10 +1064,11 @@ static int c_can_open(struct net_device *dev)
|
|||||||
goto exit_irq_fail;
|
goto exit_irq_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
napi_enable(&priv->napi);
|
||||||
|
|
||||||
/* start the c_can controller */
|
/* start the c_can controller */
|
||||||
c_can_start(dev);
|
c_can_start(dev);
|
||||||
|
|
||||||
napi_enable(&priv->napi);
|
|
||||||
netif_start_queue(dev);
|
netif_start_queue(dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -76,6 +76,7 @@ struct c_can_priv {
|
|||||||
unsigned int tx_next;
|
unsigned int tx_next;
|
||||||
unsigned int tx_echo;
|
unsigned int tx_echo;
|
||||||
void *priv; /* for board-specific data */
|
void *priv; /* for board-specific data */
|
||||||
|
u16 irqstatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct net_device *alloc_c_can_dev(void);
|
struct net_device *alloc_c_can_dev(void);
|
||||||
|
@ -154,7 +154,7 @@ static int __devinit cc770_get_platform_data(struct platform_device *pdev,
|
|||||||
struct cc770_platform_data *pdata = pdev->dev.platform_data;
|
struct cc770_platform_data *pdata = pdev->dev.platform_data;
|
||||||
|
|
||||||
priv->can.clock.freq = pdata->osc_freq;
|
priv->can.clock.freq = pdata->osc_freq;
|
||||||
if (priv->cpu_interface | CPUIF_DSC)
|
if (priv->cpu_interface & CPUIF_DSC)
|
||||||
priv->can.clock.freq /= 2;
|
priv->can.clock.freq /= 2;
|
||||||
priv->clkout = pdata->cor;
|
priv->clkout = pdata->cor;
|
||||||
priv->bus_config = pdata->bcr;
|
priv->bus_config = pdata->bcr;
|
||||||
|
@ -258,7 +258,8 @@ static int e1000_set_settings(struct net_device *netdev,
|
|||||||
* When SoL/IDER sessions are active, autoneg/speed/duplex
|
* When SoL/IDER sessions are active, autoneg/speed/duplex
|
||||||
* cannot be changed
|
* cannot be changed
|
||||||
*/
|
*/
|
||||||
if (hw->phy.ops.check_reset_block(hw)) {
|
if (hw->phy.ops.check_reset_block &&
|
||||||
|
hw->phy.ops.check_reset_block(hw)) {
|
||||||
e_err("Cannot change link characteristics when SoL/IDER is active.\n");
|
e_err("Cannot change link characteristics when SoL/IDER is active.\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1615,7 +1616,8 @@ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
|
|||||||
* PHY loopback cannot be performed if SoL/IDER
|
* PHY loopback cannot be performed if SoL/IDER
|
||||||
* sessions are active
|
* sessions are active
|
||||||
*/
|
*/
|
||||||
if (hw->phy.ops.check_reset_block(hw)) {
|
if (hw->phy.ops.check_reset_block &&
|
||||||
|
hw->phy.ops.check_reset_block(hw)) {
|
||||||
e_err("Cannot do PHY loopback test when SoL/IDER is active.\n");
|
e_err("Cannot do PHY loopback test when SoL/IDER is active.\n");
|
||||||
*data = 0;
|
*data = 0;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -709,7 +709,7 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw)
|
|||||||
* In the case of the phy reset being blocked, we already have a link.
|
* In the case of the phy reset being blocked, we already have a link.
|
||||||
* We do not need to set it up again.
|
* We do not need to set it up again.
|
||||||
*/
|
*/
|
||||||
if (hw->phy.ops.check_reset_block(hw))
|
if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -6237,7 +6237,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
|||||||
adapter->hw.phy.ms_type = e1000_ms_hw_default;
|
adapter->hw.phy.ms_type = e1000_ms_hw_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hw->phy.ops.check_reset_block(hw))
|
if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw))
|
||||||
e_info("PHY reset is blocked due to SOL/IDER session.\n");
|
e_info("PHY reset is blocked due to SOL/IDER session.\n");
|
||||||
|
|
||||||
/* Set initial default active device features */
|
/* Set initial default active device features */
|
||||||
@ -6404,7 +6404,7 @@ err_register:
|
|||||||
if (!(adapter->flags & FLAG_HAS_AMT))
|
if (!(adapter->flags & FLAG_HAS_AMT))
|
||||||
e1000e_release_hw_control(adapter);
|
e1000e_release_hw_control(adapter);
|
||||||
err_eeprom:
|
err_eeprom:
|
||||||
if (!hw->phy.ops.check_reset_block(hw))
|
if (hw->phy.ops.check_reset_block && !hw->phy.ops.check_reset_block(hw))
|
||||||
e1000_phy_hw_reset(&adapter->hw);
|
e1000_phy_hw_reset(&adapter->hw);
|
||||||
err_hw_init:
|
err_hw_init:
|
||||||
kfree(adapter->tx_ring);
|
kfree(adapter->tx_ring);
|
||||||
|
@ -2155,9 +2155,11 @@ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw)
|
|||||||
s32 ret_val;
|
s32 ret_val;
|
||||||
u32 ctrl;
|
u32 ctrl;
|
||||||
|
|
||||||
ret_val = phy->ops.check_reset_block(hw);
|
if (phy->ops.check_reset_block) {
|
||||||
if (ret_val)
|
ret_val = phy->ops.check_reset_block(hw);
|
||||||
return 0;
|
if (ret_val)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ret_val = phy->ops.acquire(hw);
|
ret_val = phy->ops.acquire(hw);
|
||||||
if (ret_val)
|
if (ret_val)
|
||||||
|
@ -1390,6 +1390,8 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
|
|||||||
union ixgbe_adv_rx_desc *rx_desc,
|
union ixgbe_adv_rx_desc *rx_desc,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
struct net_device *dev = rx_ring->netdev;
|
||||||
|
|
||||||
ixgbe_update_rsc_stats(rx_ring, skb);
|
ixgbe_update_rsc_stats(rx_ring, skb);
|
||||||
|
|
||||||
ixgbe_rx_hash(rx_ring, rx_desc, skb);
|
ixgbe_rx_hash(rx_ring, rx_desc, skb);
|
||||||
@ -1401,14 +1403,15 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
|
|||||||
ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb);
|
ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) {
|
if ((dev->features & NETIF_F_HW_VLAN_RX) &&
|
||||||
|
ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) {
|
||||||
u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan);
|
u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan);
|
||||||
__vlan_hwaccel_put_tag(skb, vid);
|
__vlan_hwaccel_put_tag(skb, vid);
|
||||||
}
|
}
|
||||||
|
|
||||||
skb_record_rx_queue(skb, rx_ring->queue_index);
|
skb_record_rx_queue(skb, rx_ring->queue_index);
|
||||||
|
|
||||||
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
|
skb->protocol = eth_type_trans(skb, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector,
|
static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector,
|
||||||
@ -3607,10 +3610,6 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
|
|||||||
if (hw->mac.type == ixgbe_mac_82598EB)
|
if (hw->mac.type == ixgbe_mac_82598EB)
|
||||||
netif_set_gso_max_size(adapter->netdev, 32768);
|
netif_set_gso_max_size(adapter->netdev, 32768);
|
||||||
|
|
||||||
|
|
||||||
/* Enable VLAN tag insert/strip */
|
|
||||||
adapter->netdev->features |= NETIF_F_HW_VLAN_RX;
|
|
||||||
|
|
||||||
hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
|
hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
|
||||||
|
|
||||||
#ifdef IXGBE_FCOE
|
#ifdef IXGBE_FCOE
|
||||||
@ -6701,11 +6700,6 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev,
|
|||||||
{
|
{
|
||||||
struct ixgbe_adapter *adapter = netdev_priv(netdev);
|
struct ixgbe_adapter *adapter = netdev_priv(netdev);
|
||||||
|
|
||||||
#ifdef CONFIG_DCB
|
|
||||||
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
|
|
||||||
features &= ~NETIF_F_HW_VLAN_RX;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* return error if RXHASH is being enabled when RSS is not supported */
|
/* return error if RXHASH is being enabled when RSS is not supported */
|
||||||
if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
|
if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
|
||||||
features &= ~NETIF_F_RXHASH;
|
features &= ~NETIF_F_RXHASH;
|
||||||
@ -6718,7 +6712,6 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev,
|
|||||||
if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE))
|
if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE))
|
||||||
features &= ~NETIF_F_LRO;
|
features &= ~NETIF_F_LRO;
|
||||||
|
|
||||||
|
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6766,6 +6759,11 @@ static int ixgbe_set_features(struct net_device *netdev,
|
|||||||
need_reset = true;
|
need_reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (features & NETIF_F_HW_VLAN_RX)
|
||||||
|
ixgbe_vlan_strip_enable(adapter);
|
||||||
|
else
|
||||||
|
ixgbe_vlan_strip_disable(adapter);
|
||||||
|
|
||||||
if (changed & NETIF_F_RXALL)
|
if (changed & NETIF_F_RXALL)
|
||||||
need_reset = true;
|
need_reset = true;
|
||||||
|
|
||||||
|
@ -436,7 +436,9 @@ struct mv643xx_eth_private {
|
|||||||
/*
|
/*
|
||||||
* Hardware-specific parameters.
|
* Hardware-specific parameters.
|
||||||
*/
|
*/
|
||||||
|
#if defined(CONFIG_HAVE_CLK)
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
#endif
|
||||||
unsigned int t_clk;
|
unsigned int t_clk;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2895,17 +2897,17 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
|
|||||||
mp->dev = dev;
|
mp->dev = dev;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the clk rate, if there is one, otherwise use the default.
|
* Start with a default rate, and if there is a clock, allow
|
||||||
|
* it to override the default.
|
||||||
*/
|
*/
|
||||||
|
mp->t_clk = 133000000;
|
||||||
|
#if defined(CONFIG_HAVE_CLK)
|
||||||
mp->clk = clk_get(&pdev->dev, (pdev->id ? "1" : "0"));
|
mp->clk = clk_get(&pdev->dev, (pdev->id ? "1" : "0"));
|
||||||
if (!IS_ERR(mp->clk)) {
|
if (!IS_ERR(mp->clk)) {
|
||||||
clk_prepare_enable(mp->clk);
|
clk_prepare_enable(mp->clk);
|
||||||
mp->t_clk = clk_get_rate(mp->clk);
|
mp->t_clk = clk_get_rate(mp->clk);
|
||||||
} else {
|
|
||||||
mp->t_clk = 133000000;
|
|
||||||
printk(KERN_WARNING "Unable to get clock");
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
set_params(mp, pd);
|
set_params(mp, pd);
|
||||||
netif_set_real_num_tx_queues(dev, mp->txq_count);
|
netif_set_real_num_tx_queues(dev, mp->txq_count);
|
||||||
netif_set_real_num_rx_queues(dev, mp->rxq_count);
|
netif_set_real_num_rx_queues(dev, mp->rxq_count);
|
||||||
@ -2995,10 +2997,13 @@ static int mv643xx_eth_remove(struct platform_device *pdev)
|
|||||||
phy_detach(mp->phy);
|
phy_detach(mp->phy);
|
||||||
cancel_work_sync(&mp->tx_timeout_task);
|
cancel_work_sync(&mp->tx_timeout_task);
|
||||||
|
|
||||||
|
#if defined(CONFIG_HAVE_CLK)
|
||||||
if (!IS_ERR(mp->clk)) {
|
if (!IS_ERR(mp->clk)) {
|
||||||
clk_disable_unprepare(mp->clk);
|
clk_disable_unprepare(mp->clk);
|
||||||
clk_put(mp->clk);
|
clk_put(mp->clk);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
free_netdev(mp->dev);
|
free_netdev(mp->dev);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
@ -13,9 +13,8 @@ config STMMAC_ETH
|
|||||||
if STMMAC_ETH
|
if STMMAC_ETH
|
||||||
|
|
||||||
config STMMAC_PLATFORM
|
config STMMAC_PLATFORM
|
||||||
tristate "STMMAC platform bus support"
|
bool "STMMAC Platform bus support"
|
||||||
depends on STMMAC_ETH
|
depends on STMMAC_ETH
|
||||||
default y
|
|
||||||
---help---
|
---help---
|
||||||
This selects the platform specific bus support for
|
This selects the platform specific bus support for
|
||||||
the stmmac device driver. This is the driver used
|
the stmmac device driver. This is the driver used
|
||||||
@ -26,7 +25,7 @@ config STMMAC_PLATFORM
|
|||||||
If unsure, say N.
|
If unsure, say N.
|
||||||
|
|
||||||
config STMMAC_PCI
|
config STMMAC_PCI
|
||||||
tristate "STMMAC support on PCI bus (EXPERIMENTAL)"
|
bool "STMMAC PCI bus support (EXPERIMENTAL)"
|
||||||
depends on STMMAC_ETH && PCI && EXPERIMENTAL
|
depends on STMMAC_ETH && PCI && EXPERIMENTAL
|
||||||
---help---
|
---help---
|
||||||
This is to select the Synopsys DWMAC available on PCI devices,
|
This is to select the Synopsys DWMAC available on PCI devices,
|
||||||
|
@ -95,7 +95,8 @@ extern int stmmac_mdio_register(struct net_device *ndev);
|
|||||||
extern void stmmac_set_ethtool_ops(struct net_device *netdev);
|
extern void stmmac_set_ethtool_ops(struct net_device *netdev);
|
||||||
extern const struct stmmac_desc_ops enh_desc_ops;
|
extern const struct stmmac_desc_ops enh_desc_ops;
|
||||||
extern const struct stmmac_desc_ops ndesc_ops;
|
extern const struct stmmac_desc_ops ndesc_ops;
|
||||||
|
extern struct pci_driver stmmac_pci_driver;
|
||||||
|
extern struct platform_driver stmmac_pltfr_driver;
|
||||||
int stmmac_freeze(struct net_device *ndev);
|
int stmmac_freeze(struct net_device *ndev);
|
||||||
int stmmac_restore(struct net_device *ndev);
|
int stmmac_restore(struct net_device *ndev);
|
||||||
int stmmac_resume(struct net_device *ndev);
|
int stmmac_resume(struct net_device *ndev);
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/prefetch.h>
|
#include <linux/prefetch.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
#ifdef CONFIG_STMMAC_DEBUG_FS
|
#ifdef CONFIG_STMMAC_DEBUG_FS
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
@ -833,8 +834,9 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* stmmac_selec_desc_mode
|
* stmmac_selec_desc_mode
|
||||||
* @dev : device pointer
|
* @priv : private structure
|
||||||
* Description: select the Enhanced/Alternate or Normal descriptors */
|
* Description: select the Enhanced/Alternate or Normal descriptors
|
||||||
|
*/
|
||||||
static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
|
static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
|
||||||
{
|
{
|
||||||
if (priv->plat->enh_desc) {
|
if (priv->plat->enh_desc) {
|
||||||
@ -1860,6 +1862,8 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
|
|||||||
/**
|
/**
|
||||||
* stmmac_dvr_probe
|
* stmmac_dvr_probe
|
||||||
* @device: device pointer
|
* @device: device pointer
|
||||||
|
* @plat_dat: platform data pointer
|
||||||
|
* @addr: iobase memory address
|
||||||
* Description: this is the main probe function used to
|
* Description: this is the main probe function used to
|
||||||
* call the alloc_etherdev, allocate the priv structure.
|
* call the alloc_etherdev, allocate the priv structure.
|
||||||
*/
|
*/
|
||||||
@ -2089,6 +2093,30 @@ int stmmac_restore(struct net_device *ndev)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
|
static int __init stmmac_init(void)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
err = platform_driver_register(&stmmac_pltfr_driver);
|
||||||
|
|
||||||
|
if (!err) {
|
||||||
|
err = pci_register_driver(&stmmac_pci_driver);
|
||||||
|
if (err)
|
||||||
|
platform_driver_unregister(&stmmac_pltfr_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit stmmac_exit(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&stmmac_pci_driver);
|
||||||
|
platform_driver_unregister(&stmmac_pltfr_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(stmmac_init);
|
||||||
|
module_exit(stmmac_exit);
|
||||||
|
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
static int __init stmmac_cmdline_opt(char *str)
|
static int __init stmmac_cmdline_opt(char *str)
|
||||||
{
|
{
|
||||||
|
@ -179,7 +179,7 @@ static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = {
|
|||||||
|
|
||||||
MODULE_DEVICE_TABLE(pci, stmmac_id_table);
|
MODULE_DEVICE_TABLE(pci, stmmac_id_table);
|
||||||
|
|
||||||
static struct pci_driver stmmac_driver = {
|
struct pci_driver stmmac_pci_driver = {
|
||||||
.name = STMMAC_RESOURCE_NAME,
|
.name = STMMAC_RESOURCE_NAME,
|
||||||
.id_table = stmmac_id_table,
|
.id_table = stmmac_id_table,
|
||||||
.probe = stmmac_pci_probe,
|
.probe = stmmac_pci_probe,
|
||||||
@ -190,33 +190,6 @@ static struct pci_driver stmmac_driver = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* stmmac_init_module - Entry point for the driver
|
|
||||||
* Description: This function is the entry point for the driver.
|
|
||||||
*/
|
|
||||||
static int __init stmmac_init_module(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = pci_register_driver(&stmmac_driver);
|
|
||||||
if (ret < 0)
|
|
||||||
pr_err("%s: ERROR: driver registration failed\n", __func__);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* stmmac_cleanup_module - Cleanup routine for the driver
|
|
||||||
* Description: This function is the cleanup routine for the driver.
|
|
||||||
*/
|
|
||||||
static void __exit stmmac_cleanup_module(void)
|
|
||||||
{
|
|
||||||
pci_unregister_driver(&stmmac_driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(stmmac_init_module);
|
|
||||||
module_exit(stmmac_cleanup_module);
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver");
|
MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver");
|
||||||
MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>");
|
MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>");
|
||||||
MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
|
MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
|
||||||
|
@ -255,7 +255,7 @@ static const struct of_device_id stmmac_dt_ids[] = {
|
|||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
|
MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
|
||||||
|
|
||||||
static struct platform_driver stmmac_driver = {
|
struct platform_driver stmmac_pltfr_driver = {
|
||||||
.probe = stmmac_pltfr_probe,
|
.probe = stmmac_pltfr_probe,
|
||||||
.remove = stmmac_pltfr_remove,
|
.remove = stmmac_pltfr_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
@ -266,8 +266,6 @@ static struct platform_driver stmmac_driver = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module_platform_driver(stmmac_driver);
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver");
|
MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver");
|
||||||
MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
|
MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -478,6 +478,7 @@ struct netvsc_device {
|
|||||||
u32 nvsp_version;
|
u32 nvsp_version;
|
||||||
|
|
||||||
atomic_t num_outstanding_sends;
|
atomic_t num_outstanding_sends;
|
||||||
|
wait_queue_head_t wait_drain;
|
||||||
bool start_remove;
|
bool start_remove;
|
||||||
bool destroy;
|
bool destroy;
|
||||||
/*
|
/*
|
||||||
|
@ -42,6 +42,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
|
|||||||
if (!net_device)
|
if (!net_device)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
init_waitqueue_head(&net_device->wait_drain);
|
||||||
net_device->start_remove = false;
|
net_device->start_remove = false;
|
||||||
net_device->destroy = false;
|
net_device->destroy = false;
|
||||||
net_device->dev = device;
|
net_device->dev = device;
|
||||||
@ -387,12 +388,8 @@ int netvsc_device_remove(struct hv_device *device)
|
|||||||
spin_unlock_irqrestore(&device->channel->inbound_lock, flags);
|
spin_unlock_irqrestore(&device->channel->inbound_lock, flags);
|
||||||
|
|
||||||
/* Wait for all send completions */
|
/* Wait for all send completions */
|
||||||
while (atomic_read(&net_device->num_outstanding_sends)) {
|
wait_event(net_device->wait_drain,
|
||||||
dev_info(&device->device,
|
atomic_read(&net_device->num_outstanding_sends) == 0);
|
||||||
"waiting for %d requests to complete...\n",
|
|
||||||
atomic_read(&net_device->num_outstanding_sends));
|
|
||||||
udelay(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
netvsc_disconnect_vsp(net_device);
|
netvsc_disconnect_vsp(net_device);
|
||||||
|
|
||||||
@ -486,6 +483,9 @@ static void netvsc_send_completion(struct hv_device *device,
|
|||||||
num_outstanding_sends =
|
num_outstanding_sends =
|
||||||
atomic_dec_return(&net_device->num_outstanding_sends);
|
atomic_dec_return(&net_device->num_outstanding_sends);
|
||||||
|
|
||||||
|
if (net_device->destroy && num_outstanding_sends == 0)
|
||||||
|
wake_up(&net_device->wait_drain);
|
||||||
|
|
||||||
if (netif_queue_stopped(ndev) && !net_device->start_remove &&
|
if (netif_queue_stopped(ndev) && !net_device->start_remove &&
|
||||||
(hv_ringbuf_avail_percent(&device->channel->outbound)
|
(hv_ringbuf_avail_percent(&device->channel->outbound)
|
||||||
> RING_AVAIL_PERCENT_HIWATER ||
|
> RING_AVAIL_PERCENT_HIWATER ||
|
||||||
|
@ -41,6 +41,8 @@ MODULE_LICENSE("GPL");
|
|||||||
#define IP1001_APS_ON 11 /* IP1001 APS Mode bit */
|
#define IP1001_APS_ON 11 /* IP1001 APS Mode bit */
|
||||||
#define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */
|
#define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */
|
||||||
#define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */
|
#define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */
|
||||||
|
#define IP101A_G_IRQ_PIN_USED (1<<15) /* INTR pin used */
|
||||||
|
#define IP101A_G_IRQ_DEFAULT IP101A_G_IRQ_PIN_USED
|
||||||
|
|
||||||
static int ip175c_config_init(struct phy_device *phydev)
|
static int ip175c_config_init(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
@ -136,6 +138,11 @@ static int ip1001_config_init(struct phy_device *phydev)
|
|||||||
if (c < 0)
|
if (c < 0)
|
||||||
return c;
|
return c;
|
||||||
|
|
||||||
|
/* INTR pin used: speed/link/duplex will cause an interrupt */
|
||||||
|
c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT);
|
||||||
|
if (c < 0)
|
||||||
|
return c;
|
||||||
|
|
||||||
if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
|
if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
|
||||||
/* Additional delay (2ns) used to adjust RX clock phase
|
/* Additional delay (2ns) used to adjust RX clock phase
|
||||||
* at RGMII interface */
|
* at RGMII interface */
|
||||||
|
@ -946,7 +946,7 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 };
|
static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 };
|
||||||
static const struct sierra_net_info_data sierra_net_info_data_68A3 = {
|
static const struct sierra_net_info_data sierra_net_info_data_direct_ip = {
|
||||||
.rx_urb_size = 8 * 1024,
|
.rx_urb_size = 8 * 1024,
|
||||||
.whitelist = {
|
.whitelist = {
|
||||||
.infolen = ARRAY_SIZE(sierra_net_ifnum_list),
|
.infolen = ARRAY_SIZE(sierra_net_ifnum_list),
|
||||||
@ -954,7 +954,7 @@ static const struct sierra_net_info_data sierra_net_info_data_68A3 = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct driver_info sierra_net_info_68A3 = {
|
static const struct driver_info sierra_net_info_direct_ip = {
|
||||||
.description = "Sierra Wireless USB-to-WWAN Modem",
|
.description = "Sierra Wireless USB-to-WWAN Modem",
|
||||||
.flags = FLAG_WWAN | FLAG_SEND_ZLP,
|
.flags = FLAG_WWAN | FLAG_SEND_ZLP,
|
||||||
.bind = sierra_net_bind,
|
.bind = sierra_net_bind,
|
||||||
@ -962,12 +962,18 @@ static const struct driver_info sierra_net_info_68A3 = {
|
|||||||
.status = sierra_net_status,
|
.status = sierra_net_status,
|
||||||
.rx_fixup = sierra_net_rx_fixup,
|
.rx_fixup = sierra_net_rx_fixup,
|
||||||
.tx_fixup = sierra_net_tx_fixup,
|
.tx_fixup = sierra_net_tx_fixup,
|
||||||
.data = (unsigned long)&sierra_net_info_data_68A3,
|
.data = (unsigned long)&sierra_net_info_data_direct_ip,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct usb_device_id products[] = {
|
static const struct usb_device_id products[] = {
|
||||||
{USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */
|
{USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */
|
||||||
.driver_info = (unsigned long) &sierra_net_info_68A3},
|
.driver_info = (unsigned long) &sierra_net_info_direct_ip},
|
||||||
|
{USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */
|
||||||
|
.driver_info = (unsigned long) &sierra_net_info_direct_ip},
|
||||||
|
{USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */
|
||||||
|
.driver_info = (unsigned long) &sierra_net_info_direct_ip},
|
||||||
|
{USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */
|
||||||
|
.driver_info = (unsigned long) &sierra_net_info_direct_ip},
|
||||||
|
|
||||||
{}, /* last item */
|
{}, /* last item */
|
||||||
};
|
};
|
||||||
|
@ -89,9 +89,9 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
|
|||||||
data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
|
data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
|
||||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
|
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
|
||||||
|
|
||||||
/* redirect, configure ane enable io for interrupt signal */
|
/* redirect, configure and enable io for interrupt signal */
|
||||||
data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
|
data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
|
||||||
if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH)
|
if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH)
|
||||||
data |= SDIO_SEPINT_ACT_HI;
|
data |= SDIO_SEPINT_ACT_HI;
|
||||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
|
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
|
||||||
|
|
||||||
|
@ -861,13 +861,18 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||||||
|
|
||||||
/* We have our copies now, allow OS release its copies */
|
/* We have our copies now, allow OS release its copies */
|
||||||
release_firmware(ucode_raw);
|
release_firmware(ucode_raw);
|
||||||
complete(&drv->request_firmware_complete);
|
|
||||||
|
|
||||||
drv->op_mode = iwl_dvm_ops.start(drv->trans, drv->cfg, &drv->fw);
|
drv->op_mode = iwl_dvm_ops.start(drv->trans, drv->cfg, &drv->fw);
|
||||||
|
|
||||||
if (!drv->op_mode)
|
if (!drv->op_mode)
|
||||||
goto out_free_fw;
|
goto out_unbind;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Complete the firmware request last so that
|
||||||
|
* a driver unbind (stop) doesn't run while we
|
||||||
|
* are doing the start() above.
|
||||||
|
*/
|
||||||
|
complete(&drv->request_firmware_complete);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try_again:
|
try_again:
|
||||||
|
@ -568,28 +568,28 @@ static int iwl_find_otp_image(struct iwl_trans *trans,
|
|||||||
* iwl_get_max_txpower_avg - get the highest tx power from all chains.
|
* iwl_get_max_txpower_avg - get the highest tx power from all chains.
|
||||||
* find the highest tx power from all chains for the channel
|
* find the highest tx power from all chains for the channel
|
||||||
*/
|
*/
|
||||||
static s8 iwl_get_max_txpower_avg(const struct iwl_cfg *cfg,
|
static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
|
||||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||||
int element, s8 *max_txpower_in_half_dbm)
|
int element, s8 *max_txpower_in_half_dbm)
|
||||||
{
|
{
|
||||||
s8 max_txpower_avg = 0; /* (dBm) */
|
s8 max_txpower_avg = 0; /* (dBm) */
|
||||||
|
|
||||||
/* Take the highest tx power from any valid chains */
|
/* Take the highest tx power from any valid chains */
|
||||||
if ((cfg->valid_tx_ant & ANT_A) &&
|
if ((priv->hw_params.valid_tx_ant & ANT_A) &&
|
||||||
(enhanced_txpower[element].chain_a_max > max_txpower_avg))
|
(enhanced_txpower[element].chain_a_max > max_txpower_avg))
|
||||||
max_txpower_avg = enhanced_txpower[element].chain_a_max;
|
max_txpower_avg = enhanced_txpower[element].chain_a_max;
|
||||||
if ((cfg->valid_tx_ant & ANT_B) &&
|
if ((priv->hw_params.valid_tx_ant & ANT_B) &&
|
||||||
(enhanced_txpower[element].chain_b_max > max_txpower_avg))
|
(enhanced_txpower[element].chain_b_max > max_txpower_avg))
|
||||||
max_txpower_avg = enhanced_txpower[element].chain_b_max;
|
max_txpower_avg = enhanced_txpower[element].chain_b_max;
|
||||||
if ((cfg->valid_tx_ant & ANT_C) &&
|
if ((priv->hw_params.valid_tx_ant & ANT_C) &&
|
||||||
(enhanced_txpower[element].chain_c_max > max_txpower_avg))
|
(enhanced_txpower[element].chain_c_max > max_txpower_avg))
|
||||||
max_txpower_avg = enhanced_txpower[element].chain_c_max;
|
max_txpower_avg = enhanced_txpower[element].chain_c_max;
|
||||||
if (((cfg->valid_tx_ant == ANT_AB) |
|
if (((priv->hw_params.valid_tx_ant == ANT_AB) |
|
||||||
(cfg->valid_tx_ant == ANT_BC) |
|
(priv->hw_params.valid_tx_ant == ANT_BC) |
|
||||||
(cfg->valid_tx_ant == ANT_AC)) &&
|
(priv->hw_params.valid_tx_ant == ANT_AC)) &&
|
||||||
(enhanced_txpower[element].mimo2_max > max_txpower_avg))
|
(enhanced_txpower[element].mimo2_max > max_txpower_avg))
|
||||||
max_txpower_avg = enhanced_txpower[element].mimo2_max;
|
max_txpower_avg = enhanced_txpower[element].mimo2_max;
|
||||||
if ((cfg->valid_tx_ant == ANT_ABC) &&
|
if ((priv->hw_params.valid_tx_ant == ANT_ABC) &&
|
||||||
(enhanced_txpower[element].mimo3_max > max_txpower_avg))
|
(enhanced_txpower[element].mimo3_max > max_txpower_avg))
|
||||||
max_txpower_avg = enhanced_txpower[element].mimo3_max;
|
max_txpower_avg = enhanced_txpower[element].mimo3_max;
|
||||||
|
|
||||||
@ -691,7 +691,7 @@ static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
|
|||||||
((txp->delta_20_in_40 & 0xf0) >> 4),
|
((txp->delta_20_in_40 & 0xf0) >> 4),
|
||||||
(txp->delta_20_in_40 & 0x0f));
|
(txp->delta_20_in_40 & 0x0f));
|
||||||
|
|
||||||
max_txp_avg = iwl_get_max_txpower_avg(priv->cfg, txp_array, idx,
|
max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx,
|
||||||
&max_txp_avg_halfdbm);
|
&max_txp_avg_halfdbm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -199,6 +199,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
|||||||
WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
||||||
WIPHY_FLAG_IBSS_RSN;
|
WIPHY_FLAG_IBSS_RSN;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
|
if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
|
||||||
priv->trans->ops->wowlan_suspend &&
|
priv->trans->ops->wowlan_suspend &&
|
||||||
device_can_wakeup(priv->trans->dev)) {
|
device_can_wakeup(priv->trans->dev)) {
|
||||||
@ -217,6 +218,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
|||||||
hw->wiphy->wowlan.pattern_max_len =
|
hw->wiphy->wowlan.pattern_max_len =
|
||||||
IWLAGN_WOWLAN_MAX_PATTERN_LEN;
|
IWLAGN_WOWLAN_MAX_PATTERN_LEN;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (iwlwifi_mod_params.power_save)
|
if (iwlwifi_mod_params.power_save)
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||||
@ -249,6 +251,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
|||||||
ret = ieee80211_register_hw(priv->hw);
|
ret = ieee80211_register_hw(priv->hw);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
|
IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
|
||||||
|
iwl_leds_exit(priv);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
priv->mac80211_registered = 1;
|
priv->mac80211_registered = 1;
|
||||||
|
@ -1721,6 +1721,24 @@ static void hwsim_exit_netlink(void)
|
|||||||
"unregister family %i\n", ret);
|
"unregister family %i\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct ieee80211_iface_limit hwsim_if_limits[] = {
|
||||||
|
{ .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
|
||||||
|
{ .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) |
|
||||||
|
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||||
|
#ifdef CONFIG_MAC80211_MESH
|
||||||
|
BIT(NL80211_IFTYPE_MESH_POINT) |
|
||||||
|
#endif
|
||||||
|
BIT(NL80211_IFTYPE_AP) |
|
||||||
|
BIT(NL80211_IFTYPE_P2P_GO) },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ieee80211_iface_combination hwsim_if_comb = {
|
||||||
|
.limits = hwsim_if_limits,
|
||||||
|
.n_limits = ARRAY_SIZE(hwsim_if_limits),
|
||||||
|
.max_interfaces = 2048,
|
||||||
|
.num_different_channels = 1,
|
||||||
|
};
|
||||||
|
|
||||||
static int __init init_mac80211_hwsim(void)
|
static int __init init_mac80211_hwsim(void)
|
||||||
{
|
{
|
||||||
int i, err = 0;
|
int i, err = 0;
|
||||||
@ -1782,6 +1800,9 @@ static int __init init_mac80211_hwsim(void)
|
|||||||
hw->wiphy->n_addresses = 2;
|
hw->wiphy->n_addresses = 2;
|
||||||
hw->wiphy->addresses = data->addresses;
|
hw->wiphy->addresses = data->addresses;
|
||||||
|
|
||||||
|
hw->wiphy->iface_combinations = &hwsim_if_comb;
|
||||||
|
hw->wiphy->n_iface_combinations = 1;
|
||||||
|
|
||||||
if (fake_hw_scan) {
|
if (fake_hw_scan) {
|
||||||
hw->wiphy->max_scan_ssids = 255;
|
hw->wiphy->max_scan_ssids = 255;
|
||||||
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
|
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
|
||||||
|
@ -948,6 +948,19 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
|||||||
bss_cfg->ssid.ssid_len = params->ssid_len;
|
bss_cfg->ssid.ssid_len = params->ssid_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (params->hidden_ssid) {
|
||||||
|
case NL80211_HIDDEN_SSID_NOT_IN_USE:
|
||||||
|
bss_cfg->bcast_ssid_ctl = 1;
|
||||||
|
break;
|
||||||
|
case NL80211_HIDDEN_SSID_ZERO_LEN:
|
||||||
|
bss_cfg->bcast_ssid_ctl = 0;
|
||||||
|
break;
|
||||||
|
case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
|
||||||
|
/* firmware doesn't support this type of hidden SSID */
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
|
if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
|
||||||
kfree(bss_cfg);
|
kfree(bss_cfg);
|
||||||
wiphy_err(wiphy, "Failed to parse secuirty parameters!\n");
|
wiphy_err(wiphy, "Failed to parse secuirty parameters!\n");
|
||||||
|
@ -122,6 +122,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
|||||||
#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42)
|
#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42)
|
||||||
#define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44)
|
#define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44)
|
||||||
#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45)
|
#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45)
|
||||||
|
#define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48)
|
||||||
#define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51)
|
#define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51)
|
||||||
#define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60)
|
#define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60)
|
||||||
#define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64)
|
#define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64)
|
||||||
@ -1209,6 +1210,11 @@ struct host_cmd_tlv_ssid {
|
|||||||
u8 ssid[0];
|
u8 ssid[0];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct host_cmd_tlv_bcast_ssid {
|
||||||
|
struct host_cmd_tlv tlv;
|
||||||
|
u8 bcast_ctl;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
struct host_cmd_tlv_beacon_period {
|
struct host_cmd_tlv_beacon_period {
|
||||||
struct host_cmd_tlv tlv;
|
struct host_cmd_tlv tlv;
|
||||||
__le16 period;
|
__le16 period;
|
||||||
|
@ -132,6 +132,7 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
|
|||||||
struct host_cmd_tlv_dtim_period *dtim_period;
|
struct host_cmd_tlv_dtim_period *dtim_period;
|
||||||
struct host_cmd_tlv_beacon_period *beacon_period;
|
struct host_cmd_tlv_beacon_period *beacon_period;
|
||||||
struct host_cmd_tlv_ssid *ssid;
|
struct host_cmd_tlv_ssid *ssid;
|
||||||
|
struct host_cmd_tlv_bcast_ssid *bcast_ssid;
|
||||||
struct host_cmd_tlv_channel_band *chan_band;
|
struct host_cmd_tlv_channel_band *chan_band;
|
||||||
struct host_cmd_tlv_frag_threshold *frag_threshold;
|
struct host_cmd_tlv_frag_threshold *frag_threshold;
|
||||||
struct host_cmd_tlv_rts_threshold *rts_threshold;
|
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)
|
|||||||
cmd_size += sizeof(struct host_cmd_tlv) +
|
cmd_size += sizeof(struct host_cmd_tlv) +
|
||||||
bss_cfg->ssid.ssid_len;
|
bss_cfg->ssid.ssid_len;
|
||||||
tlv += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len;
|
tlv += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len;
|
||||||
|
|
||||||
|
bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv;
|
||||||
|
bcast_ssid->tlv.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID);
|
||||||
|
bcast_ssid->tlv.len =
|
||||||
|
cpu_to_le16(sizeof(bcast_ssid->bcast_ctl));
|
||||||
|
bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl;
|
||||||
|
cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid);
|
||||||
|
tlv += sizeof(struct host_cmd_tlv_bcast_ssid);
|
||||||
}
|
}
|
||||||
if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) {
|
if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) {
|
||||||
chan_band = (struct host_cmd_tlv_channel_band *)tlv;
|
chan_band = (struct host_cmd_tlv_channel_band *)tlv;
|
||||||
@ -416,6 +425,7 @@ int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel)
|
|||||||
if (!bss_cfg)
|
if (!bss_cfg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
mwifiex_set_sys_config_invalid_data(bss_cfg);
|
||||||
bss_cfg->band_cfg = BAND_CONFIG_MANUAL;
|
bss_cfg->band_cfg = BAND_CONFIG_MANUAL;
|
||||||
bss_cfg->channel = channel;
|
bss_cfg->channel = channel;
|
||||||
|
|
||||||
|
@ -396,8 +396,7 @@ struct rt2x00_intf {
|
|||||||
* for hardware which doesn't support hardware
|
* for hardware which doesn't support hardware
|
||||||
* sequence counting.
|
* sequence counting.
|
||||||
*/
|
*/
|
||||||
spinlock_t seqlock;
|
atomic_t seqno;
|
||||||
u16 seqno;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
|
static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
|
||||||
|
@ -277,7 +277,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
|||||||
else
|
else
|
||||||
rt2x00dev->intf_sta_count++;
|
rt2x00dev->intf_sta_count++;
|
||||||
|
|
||||||
spin_lock_init(&intf->seqlock);
|
|
||||||
mutex_init(&intf->beacon_skb_mutex);
|
mutex_init(&intf->beacon_skb_mutex);
|
||||||
intf->beacon = entry;
|
intf->beacon = entry;
|
||||||
|
|
||||||
|
@ -207,6 +207,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev,
|
|||||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
|
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
|
||||||
|
u16 seqno;
|
||||||
|
|
||||||
if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
|
if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
|
||||||
return;
|
return;
|
||||||
@ -238,15 +239,13 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev,
|
|||||||
* sequence counting per-frame, since those will override the
|
* sequence counting per-frame, since those will override the
|
||||||
* sequence counter given by mac80211.
|
* sequence counter given by mac80211.
|
||||||
*/
|
*/
|
||||||
spin_lock(&intf->seqlock);
|
|
||||||
|
|
||||||
if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
|
if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
|
||||||
intf->seqno += 0x10;
|
seqno = atomic_add_return(0x10, &intf->seqno);
|
||||||
|
else
|
||||||
|
seqno = atomic_read(&intf->seqno);
|
||||||
|
|
||||||
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
|
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
|
||||||
hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
|
hdr->seq_ctrl |= cpu_to_le16(seqno);
|
||||||
|
|
||||||
spin_unlock(&intf->seqlock);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev,
|
static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev,
|
||||||
|
@ -40,7 +40,10 @@ struct inet_peer {
|
|||||||
u32 pmtu_orig;
|
u32 pmtu_orig;
|
||||||
u32 pmtu_learned;
|
u32 pmtu_learned;
|
||||||
struct inetpeer_addr_base redirect_learned;
|
struct inetpeer_addr_base redirect_learned;
|
||||||
struct list_head gc_list;
|
union {
|
||||||
|
struct list_head gc_list;
|
||||||
|
struct rcu_head gc_rcu;
|
||||||
|
};
|
||||||
/*
|
/*
|
||||||
* Once inet_peer is queued for deletion (refcnt == -1), following fields
|
* Once inet_peer is queued for deletion (refcnt == -1), following fields
|
||||||
* are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp
|
* are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp
|
||||||
|
@ -210,7 +210,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sk->sk_state == BT_CONNECTED || !newsock ||
|
if (sk->sk_state == BT_CONNECTED || !newsock ||
|
||||||
test_bit(BT_DEFER_SETUP, &bt_sk(parent)->flags)) {
|
test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) {
|
||||||
bt_accept_unlink(sk);
|
bt_accept_unlink(sk);
|
||||||
if (newsock)
|
if (newsock)
|
||||||
sock_graft(sk, newsock);
|
sock_graft(sk, newsock);
|
||||||
|
@ -36,9 +36,6 @@
|
|||||||
#define TRACE_ON 1
|
#define TRACE_ON 1
|
||||||
#define TRACE_OFF 0
|
#define TRACE_OFF 0
|
||||||
|
|
||||||
static void send_dm_alert(struct work_struct *unused);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Globals, our netlink socket pointer
|
* Globals, our netlink socket pointer
|
||||||
* and the work handle that will send up
|
* and the work handle that will send up
|
||||||
@ -48,11 +45,10 @@ static int trace_state = TRACE_OFF;
|
|||||||
static DEFINE_MUTEX(trace_state_mutex);
|
static DEFINE_MUTEX(trace_state_mutex);
|
||||||
|
|
||||||
struct per_cpu_dm_data {
|
struct per_cpu_dm_data {
|
||||||
struct work_struct dm_alert_work;
|
spinlock_t lock;
|
||||||
struct sk_buff __rcu *skb;
|
struct sk_buff *skb;
|
||||||
atomic_t dm_hit_count;
|
struct work_struct dm_alert_work;
|
||||||
struct timer_list send_timer;
|
struct timer_list send_timer;
|
||||||
int cpu;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dm_hw_stat_delta {
|
struct dm_hw_stat_delta {
|
||||||
@ -78,13 +74,13 @@ static int dm_delay = 1;
|
|||||||
static unsigned long dm_hw_check_delta = 2*HZ;
|
static unsigned long dm_hw_check_delta = 2*HZ;
|
||||||
static LIST_HEAD(hw_stats_list);
|
static LIST_HEAD(hw_stats_list);
|
||||||
|
|
||||||
static void reset_per_cpu_data(struct per_cpu_dm_data *data)
|
static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data)
|
||||||
{
|
{
|
||||||
size_t al;
|
size_t al;
|
||||||
struct net_dm_alert_msg *msg;
|
struct net_dm_alert_msg *msg;
|
||||||
struct nlattr *nla;
|
struct nlattr *nla;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct sk_buff *oskb = rcu_dereference_protected(data->skb, 1);
|
unsigned long flags;
|
||||||
|
|
||||||
al = sizeof(struct net_dm_alert_msg);
|
al = sizeof(struct net_dm_alert_msg);
|
||||||
al += dm_hit_limit * sizeof(struct net_dm_drop_point);
|
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)
|
|||||||
sizeof(struct net_dm_alert_msg));
|
sizeof(struct net_dm_alert_msg));
|
||||||
msg = nla_data(nla);
|
msg = nla_data(nla);
|
||||||
memset(msg, 0, al);
|
memset(msg, 0, al);
|
||||||
} else
|
} else {
|
||||||
schedule_work_on(data->cpu, &data->dm_alert_work);
|
mod_timer(&data->send_timer, jiffies + HZ / 10);
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't need to lock this, since we are guaranteed to only
|
|
||||||
* run this on a single cpu at a time.
|
|
||||||
* Note also that we only update data->skb if the old and new skb
|
|
||||||
* pointers don't match. This ensures that we don't continually call
|
|
||||||
* synchornize_rcu if we repeatedly fail to alloc a new netlink message.
|
|
||||||
*/
|
|
||||||
if (skb != oskb) {
|
|
||||||
rcu_assign_pointer(data->skb, skb);
|
|
||||||
|
|
||||||
synchronize_rcu();
|
|
||||||
|
|
||||||
atomic_set(&data->dm_hit_count, dm_hit_limit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&data->lock, flags);
|
||||||
|
swap(data->skb, skb);
|
||||||
|
spin_unlock_irqrestore(&data->lock, flags);
|
||||||
|
|
||||||
|
return skb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_dm_alert(struct work_struct *unused)
|
static void send_dm_alert(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data);
|
struct per_cpu_dm_data *data;
|
||||||
|
|
||||||
WARN_ON_ONCE(data->cpu != smp_processor_id());
|
data = container_of(work, struct per_cpu_dm_data, dm_alert_work);
|
||||||
|
|
||||||
/*
|
skb = reset_per_cpu_data(data);
|
||||||
* Grab the skb we're about to send
|
|
||||||
*/
|
|
||||||
skb = rcu_dereference_protected(data->skb, 1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Replace it with a new one
|
|
||||||
*/
|
|
||||||
reset_per_cpu_data(data);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ship it!
|
|
||||||
*/
|
|
||||||
if (skb)
|
if (skb)
|
||||||
genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
|
genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
|
||||||
|
|
||||||
put_cpu_var(dm_cpu_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the timer function to delay the sending of an alert
|
* This is the timer function to delay the sending of an alert
|
||||||
* in the event that more drops will arrive during the
|
* in the event that more drops will arrive during the
|
||||||
* hysteresis period. Note that it operates under the timer interrupt
|
* hysteresis period.
|
||||||
* so we don't need to disable preemption here
|
|
||||||
*/
|
*/
|
||||||
static void sched_send_work(unsigned long unused)
|
static void sched_send_work(unsigned long _data)
|
||||||
{
|
{
|
||||||
struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data);
|
struct per_cpu_dm_data *data = (struct per_cpu_dm_data *)_data;
|
||||||
|
|
||||||
schedule_work_on(smp_processor_id(), &data->dm_alert_work);
|
schedule_work(&data->dm_alert_work);
|
||||||
|
|
||||||
put_cpu_var(dm_cpu_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trace_drop_common(struct sk_buff *skb, void *location)
|
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)
|
|||||||
struct nlattr *nla;
|
struct nlattr *nla;
|
||||||
int i;
|
int i;
|
||||||
struct sk_buff *dskb;
|
struct sk_buff *dskb;
|
||||||
struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data);
|
struct per_cpu_dm_data *data;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
rcu_read_lock();
|
data = &__get_cpu_var(dm_cpu_data);
|
||||||
dskb = rcu_dereference(data->skb);
|
spin_lock(&data->lock);
|
||||||
|
dskb = data->skb;
|
||||||
|
|
||||||
if (!dskb)
|
if (!dskb)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!atomic_add_unless(&data->dm_hit_count, -1, 0)) {
|
|
||||||
/*
|
|
||||||
* we're already at zero, discard this hit
|
|
||||||
*/
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
nlh = (struct nlmsghdr *)dskb->data;
|
nlh = (struct nlmsghdr *)dskb->data;
|
||||||
nla = genlmsg_data(nlmsg_data(nlh));
|
nla = genlmsg_data(nlmsg_data(nlh));
|
||||||
msg = nla_data(nla);
|
msg = nla_data(nla);
|
||||||
for (i = 0; i < msg->entries; i++) {
|
for (i = 0; i < msg->entries; i++) {
|
||||||
if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) {
|
if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) {
|
||||||
msg->points[i].count++;
|
msg->points[i].count++;
|
||||||
atomic_inc(&data->dm_hit_count);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (msg->entries == dm_hit_limit)
|
||||||
|
goto out;
|
||||||
/*
|
/*
|
||||||
* We need to create a new entry
|
* We need to create a new entry
|
||||||
*/
|
*/
|
||||||
@ -205,13 +171,11 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
|
|||||||
|
|
||||||
if (!timer_pending(&data->send_timer)) {
|
if (!timer_pending(&data->send_timer)) {
|
||||||
data->send_timer.expires = jiffies + dm_delay * HZ;
|
data->send_timer.expires = jiffies + dm_delay * HZ;
|
||||||
add_timer_on(&data->send_timer, smp_processor_id());
|
add_timer(&data->send_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
rcu_read_unlock();
|
spin_unlock_irqrestore(&data->lock, flags);
|
||||||
put_cpu_var(dm_cpu_data);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trace_kfree_skb_hit(void *ignore, struct sk_buff *skb, void *location)
|
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)
|
|||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
data = &per_cpu(dm_cpu_data, cpu);
|
data = &per_cpu(dm_cpu_data, cpu);
|
||||||
data->cpu = cpu;
|
|
||||||
INIT_WORK(&data->dm_alert_work, send_dm_alert);
|
INIT_WORK(&data->dm_alert_work, send_dm_alert);
|
||||||
init_timer(&data->send_timer);
|
init_timer(&data->send_timer);
|
||||||
data->send_timer.data = cpu;
|
data->send_timer.data = (unsigned long)data;
|
||||||
data->send_timer.function = sched_send_work;
|
data->send_timer.function = sched_send_work;
|
||||||
|
spin_lock_init(&data->lock);
|
||||||
reset_per_cpu_data(data);
|
reset_per_cpu_data(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,6 +560,17 @@ bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(inet_peer_xrlim_allow);
|
EXPORT_SYMBOL(inet_peer_xrlim_allow);
|
||||||
|
|
||||||
|
static void inetpeer_inval_rcu(struct rcu_head *head)
|
||||||
|
{
|
||||||
|
struct inet_peer *p = container_of(head, struct inet_peer, gc_rcu);
|
||||||
|
|
||||||
|
spin_lock_bh(&gc_lock);
|
||||||
|
list_add_tail(&p->gc_list, &gc_list);
|
||||||
|
spin_unlock_bh(&gc_lock);
|
||||||
|
|
||||||
|
schedule_delayed_work(&gc_work, gc_delay);
|
||||||
|
}
|
||||||
|
|
||||||
void inetpeer_invalidate_tree(int family)
|
void inetpeer_invalidate_tree(int family)
|
||||||
{
|
{
|
||||||
struct inet_peer *old, *new, *prev;
|
struct inet_peer *old, *new, *prev;
|
||||||
@ -576,10 +587,7 @@ void inetpeer_invalidate_tree(int family)
|
|||||||
prev = cmpxchg(&base->root, old, new);
|
prev = cmpxchg(&base->root, old, new);
|
||||||
if (prev == old) {
|
if (prev == old) {
|
||||||
base->total = 0;
|
base->total = 0;
|
||||||
spin_lock(&gc_lock);
|
call_rcu(&prev->gc_rcu, inetpeer_inval_rcu);
|
||||||
list_add_tail(&prev->gc_list, &gc_list);
|
|
||||||
spin_unlock(&gc_lock);
|
|
||||||
schedule_delayed_work(&gc_work, gc_delay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -145,15 +145,20 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)
|
|||||||
struct tid_ampdu_rx *tid_rx;
|
struct tid_ampdu_rx *tid_rx;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]);
|
tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]);
|
||||||
if (!tid_rx)
|
if (!tid_rx) {
|
||||||
|
rcu_read_unlock();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout);
|
timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout);
|
||||||
if (time_is_after_jiffies(timeout)) {
|
if (time_is_after_jiffies(timeout)) {
|
||||||
mod_timer(&tid_rx->session_timer, timeout);
|
mod_timer(&tid_rx->session_timer, timeout);
|
||||||
|
rcu_read_unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
#ifdef CONFIG_MAC80211_HT_DEBUG
|
#ifdef CONFIG_MAC80211_HT_DEBUG
|
||||||
printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
|
printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
|
||||||
|
@ -533,16 +533,16 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
|
|||||||
sinfo.filled = 0;
|
sinfo.filled = 0;
|
||||||
sta_set_sinfo(sta, &sinfo);
|
sta_set_sinfo(sta, &sinfo);
|
||||||
|
|
||||||
if (sinfo.filled | STATION_INFO_TX_BITRATE)
|
if (sinfo.filled & STATION_INFO_TX_BITRATE)
|
||||||
data[i] = 100000 *
|
data[i] = 100000 *
|
||||||
cfg80211_calculate_bitrate(&sinfo.txrate);
|
cfg80211_calculate_bitrate(&sinfo.txrate);
|
||||||
i++;
|
i++;
|
||||||
if (sinfo.filled | STATION_INFO_RX_BITRATE)
|
if (sinfo.filled & STATION_INFO_RX_BITRATE)
|
||||||
data[i] = 100000 *
|
data[i] = 100000 *
|
||||||
cfg80211_calculate_bitrate(&sinfo.rxrate);
|
cfg80211_calculate_bitrate(&sinfo.rxrate);
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if (sinfo.filled | STATION_INFO_SIGNAL_AVG)
|
if (sinfo.filled & STATION_INFO_SIGNAL_AVG)
|
||||||
data[i] = (u8)sinfo.signal_avg;
|
data[i] = (u8)sinfo.signal_avg;
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -637,6 +637,18 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
|||||||
ieee80211_configure_filter(local);
|
ieee80211_configure_filter(local);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
mutex_lock(&local->mtx);
|
||||||
|
if (local->hw_roc_dev == sdata->dev &&
|
||||||
|
local->hw_roc_channel) {
|
||||||
|
/* ignore return value since this is racy */
|
||||||
|
drv_cancel_remain_on_channel(local);
|
||||||
|
ieee80211_queue_work(&local->hw, &local->hw_roc_done);
|
||||||
|
}
|
||||||
|
mutex_unlock(&local->mtx);
|
||||||
|
|
||||||
|
flush_work(&local->hw_roc_start);
|
||||||
|
flush_work(&local->hw_roc_done);
|
||||||
|
|
||||||
flush_work(&sdata->work);
|
flush_work(&sdata->work);
|
||||||
/*
|
/*
|
||||||
* When we get here, the interface is marked down.
|
* When we get here, the interface is marked down.
|
||||||
|
@ -1220,6 +1220,22 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
|
|||||||
sdata->vif.bss_conf.qos = true;
|
sdata->vif.bss_conf.qos = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata)
|
||||||
|
{
|
||||||
|
lockdep_assert_held(&sdata->local->mtx);
|
||||||
|
|
||||||
|
sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
|
||||||
|
IEEE80211_STA_BEACON_POLL);
|
||||||
|
ieee80211_run_deferred_scan(sdata->local);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata)
|
||||||
|
{
|
||||||
|
mutex_lock(&sdata->local->mtx);
|
||||||
|
__ieee80211_stop_poll(sdata);
|
||||||
|
mutex_unlock(&sdata->local->mtx);
|
||||||
|
}
|
||||||
|
|
||||||
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
|
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
|
||||||
u16 capab, bool erp_valid, u8 erp)
|
u16 capab, bool erp_valid, u8 erp)
|
||||||
{
|
{
|
||||||
@ -1285,8 +1301,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
|
|||||||
sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;
|
sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;
|
||||||
|
|
||||||
/* just to be sure */
|
/* just to be sure */
|
||||||
sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
|
ieee80211_stop_poll(sdata);
|
||||||
IEEE80211_STA_BEACON_POLL);
|
|
||||||
|
|
||||||
ieee80211_led_assoc(local, 1);
|
ieee80211_led_assoc(local, 1);
|
||||||
|
|
||||||
@ -1456,8 +1471,7 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
|
__ieee80211_stop_poll(sdata);
|
||||||
IEEE80211_STA_BEACON_POLL);
|
|
||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
mutex_lock(&local->iflist_mtx);
|
||||||
ieee80211_recalc_ps(local, -1);
|
ieee80211_recalc_ps(local, -1);
|
||||||
@ -1477,7 +1491,6 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
|
|||||||
round_jiffies_up(jiffies +
|
round_jiffies_up(jiffies +
|
||||||
IEEE80211_CONNECTION_IDLE_TIME));
|
IEEE80211_CONNECTION_IDLE_TIME));
|
||||||
out:
|
out:
|
||||||
ieee80211_run_deferred_scan(local);
|
|
||||||
mutex_unlock(&local->mtx);
|
mutex_unlock(&local->mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2408,7 +2421,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
|||||||
net_dbg_ratelimited("%s: cancelling probereq poll due to a received beacon\n",
|
net_dbg_ratelimited("%s: cancelling probereq poll due to a received beacon\n",
|
||||||
sdata->name);
|
sdata->name);
|
||||||
#endif
|
#endif
|
||||||
|
mutex_lock(&local->mtx);
|
||||||
ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL;
|
ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL;
|
||||||
|
ieee80211_run_deferred_scan(local);
|
||||||
|
mutex_unlock(&local->mtx);
|
||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
mutex_lock(&local->iflist_mtx);
|
||||||
ieee80211_recalc_ps(local, -1);
|
ieee80211_recalc_ps(local, -1);
|
||||||
mutex_unlock(&local->iflist_mtx);
|
mutex_unlock(&local->iflist_mtx);
|
||||||
@ -2595,8 +2612,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
|
|||||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||||
u8 frame_buf[DEAUTH_DISASSOC_LEN];
|
u8 frame_buf[DEAUTH_DISASSOC_LEN];
|
||||||
|
|
||||||
ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
|
ieee80211_stop_poll(sdata);
|
||||||
IEEE80211_STA_BEACON_POLL);
|
|
||||||
|
|
||||||
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
|
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
|
||||||
false, frame_buf);
|
false, frame_buf);
|
||||||
@ -2874,8 +2890,7 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
|
|||||||
u32 flags;
|
u32 flags;
|
||||||
|
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||||
sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL |
|
__ieee80211_stop_poll(sdata);
|
||||||
IEEE80211_STA_CONNECTION_POLL);
|
|
||||||
|
|
||||||
/* let's probe the connection once */
|
/* let's probe the connection once */
|
||||||
flags = sdata->local->hw.flags;
|
flags = sdata->local->hw.flags;
|
||||||
@ -2944,7 +2959,10 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
|
|||||||
if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running))
|
if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running))
|
||||||
add_timer(&ifmgd->chswitch_timer);
|
add_timer(&ifmgd->chswitch_timer);
|
||||||
ieee80211_sta_reset_beacon_monitor(sdata);
|
ieee80211_sta_reset_beacon_monitor(sdata);
|
||||||
|
|
||||||
|
mutex_lock(&sdata->local->mtx);
|
||||||
ieee80211_restart_sta_timer(sdata);
|
ieee80211_restart_sta_timer(sdata);
|
||||||
|
mutex_unlock(&sdata->local->mtx);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -234,6 +234,22 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* was never transmitted */
|
||||||
|
if (local->hw_roc_skb) {
|
||||||
|
u64 cookie;
|
||||||
|
|
||||||
|
cookie = local->hw_roc_cookie ^ 2;
|
||||||
|
|
||||||
|
cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie,
|
||||||
|
local->hw_roc_skb->data,
|
||||||
|
local->hw_roc_skb->len, false,
|
||||||
|
GFP_KERNEL);
|
||||||
|
|
||||||
|
kfree_skb(local->hw_roc_skb);
|
||||||
|
local->hw_roc_skb = NULL;
|
||||||
|
local->hw_roc_skb_for_status = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!local->hw_roc_for_tx)
|
if (!local->hw_roc_for_tx)
|
||||||
cfg80211_remain_on_channel_expired(local->hw_roc_dev,
|
cfg80211_remain_on_channel_expired(local->hw_roc_dev,
|
||||||
local->hw_roc_cookie,
|
local->hw_roc_cookie,
|
||||||
|
@ -378,7 +378,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
|||||||
/* make the station visible */
|
/* make the station visible */
|
||||||
sta_info_hash_add(local, sta);
|
sta_info_hash_add(local, sta);
|
||||||
|
|
||||||
list_add(&sta->list, &local->sta_list);
|
list_add_rcu(&sta->list, &local->sta_list);
|
||||||
|
|
||||||
set_sta_flag(sta, WLAN_STA_INSERTED);
|
set_sta_flag(sta, WLAN_STA_INSERTED);
|
||||||
|
|
||||||
@ -688,7 +688,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
list_del(&sta->list);
|
list_del_rcu(&sta->list);
|
||||||
|
|
||||||
mutex_lock(&local->key_mtx);
|
mutex_lock(&local->key_mtx);
|
||||||
for (i = 0; i < NUM_DEFAULT_KEYS; i++)
|
for (i = 0; i < NUM_DEFAULT_KEYS; i++)
|
||||||
|
@ -1737,7 +1737,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
|||||||
__le16 fc;
|
__le16 fc;
|
||||||
struct ieee80211_hdr hdr;
|
struct ieee80211_hdr hdr;
|
||||||
struct ieee80211s_hdr mesh_hdr __maybe_unused;
|
struct ieee80211s_hdr mesh_hdr __maybe_unused;
|
||||||
struct mesh_path __maybe_unused *mppath = NULL;
|
struct mesh_path __maybe_unused *mppath = NULL, *mpath = NULL;
|
||||||
const u8 *encaps_data;
|
const u8 *encaps_data;
|
||||||
int encaps_len, skip_header_bytes;
|
int encaps_len, skip_header_bytes;
|
||||||
int nh_pos, h_pos;
|
int nh_pos, h_pos;
|
||||||
@ -1803,8 +1803,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
if (!is_multicast_ether_addr(skb->data))
|
if (!is_multicast_ether_addr(skb->data)) {
|
||||||
mppath = mpp_path_lookup(skb->data, sdata);
|
mpath = mesh_path_lookup(skb->data, sdata);
|
||||||
|
if (!mpath)
|
||||||
|
mppath = mpp_path_lookup(skb->data, sdata);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use address extension if it is a packet from
|
* Use address extension if it is a packet from
|
||||||
|
@ -1271,7 +1271,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||||||
enum ieee80211_sta_state state;
|
enum ieee80211_sta_state state;
|
||||||
|
|
||||||
for (state = IEEE80211_STA_NOTEXIST;
|
for (state = IEEE80211_STA_NOTEXIST;
|
||||||
state < sta->sta_state - 1; state++)
|
state < sta->sta_state; state++)
|
||||||
WARN_ON(drv_sta_state(local, sta->sdata, sta,
|
WARN_ON(drv_sta_state(local, sta->sdata, sta,
|
||||||
state, state + 1));
|
state, state + 1));
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
|||||||
cfg80211_hold_bss(bss_from_pub(bss));
|
cfg80211_hold_bss(bss_from_pub(bss));
|
||||||
wdev->current_bss = bss_from_pub(bss);
|
wdev->current_bss = bss_from_pub(bss);
|
||||||
|
|
||||||
|
wdev->sme_state = CFG80211_SME_CONNECTED;
|
||||||
cfg80211_upload_connect_keys(wdev);
|
cfg80211_upload_connect_keys(wdev);
|
||||||
|
|
||||||
nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid,
|
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)
|
|||||||
struct cfg80211_event *ev;
|
struct cfg80211_event *ev;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
CFG80211_DEV_WARN_ON(!wdev->ssid_len);
|
CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING);
|
||||||
|
|
||||||
ev = kzalloc(sizeof(*ev), gfp);
|
ev = kzalloc(sizeof(*ev), gfp);
|
||||||
if (!ev)
|
if (!ev)
|
||||||
@ -115,9 +116,11 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
|||||||
#ifdef CONFIG_CFG80211_WEXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
wdev->wext.ibss.channel = params->channel;
|
wdev->wext.ibss.channel = params->channel;
|
||||||
#endif
|
#endif
|
||||||
|
wdev->sme_state = CFG80211_SME_CONNECTING;
|
||||||
err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
|
err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
|
||||||
if (err) {
|
if (err) {
|
||||||
wdev->connect_keys = NULL;
|
wdev->connect_keys = NULL;
|
||||||
|
wdev->sme_state = CFG80211_SME_IDLE;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +172,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wdev->current_bss = NULL;
|
wdev->current_bss = NULL;
|
||||||
|
wdev->sme_state = CFG80211_SME_IDLE;
|
||||||
wdev->ssid_len = 0;
|
wdev->ssid_len = 0;
|
||||||
#ifdef CONFIG_CFG80211_WEXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
if (!nowext)
|
if (!nowext)
|
||||||
|
@ -935,6 +935,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
|
|||||||
enum nl80211_iftype iftype)
|
enum nl80211_iftype iftype)
|
||||||
{
|
{
|
||||||
struct wireless_dev *wdev_iter;
|
struct wireless_dev *wdev_iter;
|
||||||
|
u32 used_iftypes = BIT(iftype);
|
||||||
int num[NUM_NL80211_IFTYPES];
|
int num[NUM_NL80211_IFTYPES];
|
||||||
int total = 1;
|
int total = 1;
|
||||||
int i, j;
|
int i, j;
|
||||||
@ -961,6 +962,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
|
|||||||
|
|
||||||
num[wdev_iter->iftype]++;
|
num[wdev_iter->iftype]++;
|
||||||
total++;
|
total++;
|
||||||
|
used_iftypes |= BIT(wdev_iter->iftype);
|
||||||
}
|
}
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
|
|
||||||
@ -970,6 +972,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
|
|||||||
for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {
|
for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {
|
||||||
const struct ieee80211_iface_combination *c;
|
const struct ieee80211_iface_combination *c;
|
||||||
struct ieee80211_iface_limit *limits;
|
struct ieee80211_iface_limit *limits;
|
||||||
|
u32 all_iftypes = 0;
|
||||||
|
|
||||||
c = &rdev->wiphy.iface_combinations[i];
|
c = &rdev->wiphy.iface_combinations[i];
|
||||||
|
|
||||||
@ -984,6 +987,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
|
|||||||
if (rdev->wiphy.software_iftypes & BIT(iftype))
|
if (rdev->wiphy.software_iftypes & BIT(iftype))
|
||||||
continue;
|
continue;
|
||||||
for (j = 0; j < c->n_limits; j++) {
|
for (j = 0; j < c->n_limits; j++) {
|
||||||
|
all_iftypes |= limits[j].types;
|
||||||
if (!(limits[j].types & BIT(iftype)))
|
if (!(limits[j].types & BIT(iftype)))
|
||||||
continue;
|
continue;
|
||||||
if (limits[j].max < num[iftype])
|
if (limits[j].max < num[iftype])
|
||||||
@ -991,7 +995,20 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
|
|||||||
limits[j].max -= num[iftype];
|
limits[j].max -= num[iftype];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* yay, it fits */
|
|
||||||
|
/*
|
||||||
|
* Finally check that all iftypes that we're currently
|
||||||
|
* using are actually part of this combination. If they
|
||||||
|
* aren't then we can't use this combination and have
|
||||||
|
* to continue to the next.
|
||||||
|
*/
|
||||||
|
if ((all_iftypes & used_iftypes) != used_iftypes)
|
||||||
|
goto cont;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This combination covered all interface types and
|
||||||
|
* supported the requested numbers, so we're good.
|
||||||
|
*/
|
||||||
kfree(limits);
|
kfree(limits);
|
||||||
return 0;
|
return 0;
|
||||||
cont:
|
cont:
|
||||||
|
Loading…
Reference in New Issue
Block a user