mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-13 14:24:11 +08:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: 1) Really fix tuntap SKB use after free bug, from Eric Dumazet. 2) Adjust SKB data pointer to point past the transport header before calling icmpv6_notify() so that the headers are in the state which that function expects. From Duan Jiong. 3) Fix ambiguities in the new tuntap multi-queue APIs. From Jason Wang. 4) mISDN needs to use del_timer_sync(), from Konstantin Khlebnikov. 5) Don't destroy mutex after freeing up device private in mac802154, fix also from Konstantin Khlebnikov. 6) Fix INET request socket leak in TCP and DCCP, from Christoph Paasch. 7) SCTP HMAC kconfig rework, from Neil Horman. 8) Fix SCTP jprobes function signature, otherwise things explode, from Daniel Borkmann. 9) Fix typo in ipv6-offload Makefile variable reference, from Simon Arlott. 10) Don't fail USBNET open just because remote wakeup isn't supported, from Oliver Neukum. 11) be2net driver bug fixes from Sathya Perla. 12) SOLOS PCI ATM driver bug fixes from Nathan Williams and David Woodhouse. 13) Fix MTU changing regression in 8139cp driver, from John Greene. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (45 commits) solos-pci: ensure all TX packets are aligned to 4 bytes solos-pci: add firmware upgrade support for new models solos-pci: remove superfluous debug output solos-pci: add GPIO support for newer versions on Geos board 8139cp: Prevent dev_close/cp_interrupt race on MTU change net: qmi_wwan: add ZTE MF880 drivers/net: Use of_match_ptr() macro in smsc911x.c drivers/net: Use of_match_ptr() macro in smc91x.c ipv6: addrconf.c: remove unnecessary "if" bridge: Correctly encode addresses when dumping mdb entries bridge: Do not unregister all PF_BRIDGE rtnl operations use generic usbnet_manage_power() usbnet: generic manage_power() usbnet: handle PM failure gracefully ksz884x: fix receive polling race condition qlcnic: update driver version qlcnic: fix unused variable warnings net: fec: forbid FEC_PTP on SoCs that do not support be2net: fix wrong frag_idx reported by RX CQ be2net: fix be_close() to ensure all events are ack'ed ...
This commit is contained in:
commit
9eb127cc04
@ -42,7 +42,8 @@
|
||||
#include <linux/swab.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define VERSION "0.07"
|
||||
#define VERSION "1.04"
|
||||
#define DRIVER_VERSION 0x01
|
||||
#define PTAG "solos-pci"
|
||||
|
||||
#define CONFIG_RAM_SIZE 128
|
||||
@ -56,16 +57,21 @@
|
||||
#define FLASH_BUSY 0x60
|
||||
#define FPGA_MODE 0x5C
|
||||
#define FLASH_MODE 0x58
|
||||
#define GPIO_STATUS 0x54
|
||||
#define DRIVER_VER 0x50
|
||||
#define TX_DMA_ADDR(port) (0x40 + (4 * (port)))
|
||||
#define RX_DMA_ADDR(port) (0x30 + (4 * (port)))
|
||||
|
||||
#define DATA_RAM_SIZE 32768
|
||||
#define BUF_SIZE 2048
|
||||
#define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/
|
||||
#define FPGA_PAGE 528 /* FPGA flash page size*/
|
||||
#define SOLOS_PAGE 512 /* Solos flash page size*/
|
||||
#define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/
|
||||
#define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/
|
||||
/* Old boards use ATMEL AD45DB161D flash */
|
||||
#define ATMEL_FPGA_PAGE 528 /* FPGA flash page size*/
|
||||
#define ATMEL_SOLOS_PAGE 512 /* Solos flash page size*/
|
||||
#define ATMEL_FPGA_BLOCK (ATMEL_FPGA_PAGE * 8) /* FPGA block size*/
|
||||
#define ATMEL_SOLOS_BLOCK (ATMEL_SOLOS_PAGE * 8) /* Solos block size*/
|
||||
/* Current boards use M25P/M25PE SPI flash */
|
||||
#define SPI_FLASH_BLOCK (256 * 64)
|
||||
|
||||
#define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2)
|
||||
#define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size))
|
||||
@ -122,11 +128,14 @@ struct solos_card {
|
||||
struct sk_buff_head cli_queue[4];
|
||||
struct sk_buff *tx_skb[4];
|
||||
struct sk_buff *rx_skb[4];
|
||||
unsigned char *dma_bounce;
|
||||
wait_queue_head_t param_wq;
|
||||
wait_queue_head_t fw_wq;
|
||||
int using_dma;
|
||||
int dma_alignment;
|
||||
int fpga_version;
|
||||
int buffer_size;
|
||||
int atmel_flash;
|
||||
};
|
||||
|
||||
|
||||
@ -451,7 +460,6 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr,
|
||||
|
||||
len = skb->len;
|
||||
memcpy(buf, skb->data, len);
|
||||
dev_dbg(&card->dev->dev, "len: %d\n", len);
|
||||
|
||||
kfree_skb(skb);
|
||||
return len;
|
||||
@ -498,6 +506,78 @@ static ssize_t console_store(struct device *dev, struct device_attribute *attr,
|
||||
return err?:count;
|
||||
}
|
||||
|
||||
struct geos_gpio_attr {
|
||||
struct device_attribute attr;
|
||||
int offset;
|
||||
};
|
||||
|
||||
#define SOLOS_GPIO_ATTR(_name, _mode, _show, _store, _offset) \
|
||||
struct geos_gpio_attr gpio_attr_##_name = { \
|
||||
.attr = __ATTR(_name, _mode, _show, _store), \
|
||||
.offset = _offset }
|
||||
|
||||
static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
|
||||
struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
|
||||
struct solos_card *card = pci_get_drvdata(pdev);
|
||||
uint32_t data32;
|
||||
|
||||
if (count != 1 && (count != 2 || buf[1] != '\n'))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irq(&card->param_queue_lock);
|
||||
data32 = ioread32(card->config_regs + GPIO_STATUS);
|
||||
if (buf[0] == '1') {
|
||||
data32 |= 1 << gattr->offset;
|
||||
iowrite32(data32, card->config_regs + GPIO_STATUS);
|
||||
} else if (buf[0] == '0') {
|
||||
data32 &= ~(1 << gattr->offset);
|
||||
iowrite32(data32, card->config_regs + GPIO_STATUS);
|
||||
} else {
|
||||
count = -EINVAL;
|
||||
}
|
||||
spin_lock_irq(&card->param_queue_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
|
||||
struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
|
||||
struct solos_card *card = pci_get_drvdata(pdev);
|
||||
uint32_t data32;
|
||||
|
||||
data32 = ioread32(card->config_regs + GPIO_STATUS);
|
||||
data32 = (data32 >> gattr->offset) & 1;
|
||||
|
||||
return sprintf(buf, "%d\n", data32);
|
||||
}
|
||||
|
||||
static ssize_t hardware_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
|
||||
struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
|
||||
struct solos_card *card = pci_get_drvdata(pdev);
|
||||
uint32_t data32;
|
||||
|
||||
data32 = ioread32(card->config_regs + GPIO_STATUS);
|
||||
switch (gattr->offset) {
|
||||
case 0:
|
||||
/* HardwareVersion */
|
||||
data32 = data32 & 0x1F;
|
||||
break;
|
||||
case 1:
|
||||
/* HardwareVariant */
|
||||
data32 = (data32 >> 5) & 0x0F;
|
||||
break;
|
||||
}
|
||||
return sprintf(buf, "%d\n", data32);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(console, 0644, console_show, console_store);
|
||||
|
||||
|
||||
@ -506,6 +586,14 @@ static DEVICE_ATTR(console, 0644, console_show, console_store);
|
||||
|
||||
#include "solos-attrlist.c"
|
||||
|
||||
static SOLOS_GPIO_ATTR(GPIO1, 0644, geos_gpio_show, geos_gpio_store, 9);
|
||||
static SOLOS_GPIO_ATTR(GPIO2, 0644, geos_gpio_show, geos_gpio_store, 10);
|
||||
static SOLOS_GPIO_ATTR(GPIO3, 0644, geos_gpio_show, geos_gpio_store, 11);
|
||||
static SOLOS_GPIO_ATTR(GPIO4, 0644, geos_gpio_show, geos_gpio_store, 12);
|
||||
static SOLOS_GPIO_ATTR(GPIO5, 0644, geos_gpio_show, geos_gpio_store, 13);
|
||||
static SOLOS_GPIO_ATTR(PushButton, 0444, geos_gpio_show, NULL, 14);
|
||||
static SOLOS_GPIO_ATTR(HardwareVersion, 0444, hardware_show, NULL, 0);
|
||||
static SOLOS_GPIO_ATTR(HardwareVariant, 0444, hardware_show, NULL, 1);
|
||||
#undef SOLOS_ATTR_RO
|
||||
#undef SOLOS_ATTR_RW
|
||||
|
||||
@ -522,6 +610,23 @@ static struct attribute_group solos_attr_group = {
|
||||
.name = "parameters",
|
||||
};
|
||||
|
||||
static struct attribute *gpio_attrs[] = {
|
||||
&gpio_attr_GPIO1.attr.attr,
|
||||
&gpio_attr_GPIO2.attr.attr,
|
||||
&gpio_attr_GPIO3.attr.attr,
|
||||
&gpio_attr_GPIO4.attr.attr,
|
||||
&gpio_attr_GPIO5.attr.attr,
|
||||
&gpio_attr_PushButton.attr.attr,
|
||||
&gpio_attr_HardwareVersion.attr.attr,
|
||||
&gpio_attr_HardwareVariant.attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group gpio_attr_group = {
|
||||
.attrs = gpio_attrs,
|
||||
.name = "gpio",
|
||||
};
|
||||
|
||||
static int flash_upgrade(struct solos_card *card, int chip)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
@ -533,16 +638,25 @@ static int flash_upgrade(struct solos_card *card, int chip)
|
||||
switch (chip) {
|
||||
case 0:
|
||||
fw_name = "solos-FPGA.bin";
|
||||
blocksize = FPGA_BLOCK;
|
||||
if (card->atmel_flash)
|
||||
blocksize = ATMEL_FPGA_BLOCK;
|
||||
else
|
||||
blocksize = SPI_FLASH_BLOCK;
|
||||
break;
|
||||
case 1:
|
||||
fw_name = "solos-Firmware.bin";
|
||||
blocksize = SOLOS_BLOCK;
|
||||
if (card->atmel_flash)
|
||||
blocksize = ATMEL_SOLOS_BLOCK;
|
||||
else
|
||||
blocksize = SPI_FLASH_BLOCK;
|
||||
break;
|
||||
case 2:
|
||||
if (card->fpga_version > LEGACY_BUFFERS){
|
||||
fw_name = "solos-db-FPGA.bin";
|
||||
blocksize = FPGA_BLOCK;
|
||||
if (card->atmel_flash)
|
||||
blocksize = ATMEL_FPGA_BLOCK;
|
||||
else
|
||||
blocksize = SPI_FLASH_BLOCK;
|
||||
} else {
|
||||
dev_info(&card->dev->dev, "FPGA version doesn't support"
|
||||
" daughter board upgrades\n");
|
||||
@ -552,7 +666,10 @@ static int flash_upgrade(struct solos_card *card, int chip)
|
||||
case 3:
|
||||
if (card->fpga_version > LEGACY_BUFFERS){
|
||||
fw_name = "solos-Firmware.bin";
|
||||
blocksize = SOLOS_BLOCK;
|
||||
if (card->atmel_flash)
|
||||
blocksize = ATMEL_SOLOS_BLOCK;
|
||||
else
|
||||
blocksize = SPI_FLASH_BLOCK;
|
||||
} else {
|
||||
dev_info(&card->dev->dev, "FPGA version doesn't support"
|
||||
" daughter board upgrades\n");
|
||||
@ -568,6 +685,9 @@ static int flash_upgrade(struct solos_card *card, int chip)
|
||||
|
||||
dev_info(&card->dev->dev, "Flash upgrade starting\n");
|
||||
|
||||
/* New FPGAs require driver version before permitting flash upgrades */
|
||||
iowrite32(DRIVER_VERSION, card->config_regs + DRIVER_VER);
|
||||
|
||||
numblocks = fw->size / blocksize;
|
||||
dev_info(&card->dev->dev, "Firmware size: %zd\n", fw->size);
|
||||
dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks);
|
||||
@ -597,9 +717,13 @@ static int flash_upgrade(struct solos_card *card, int chip)
|
||||
/* dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n"); */
|
||||
iowrite32(((chip * 2) + 1), card->config_regs + FLASH_MODE);
|
||||
|
||||
/* Copy block to buffer, swapping each 16 bits */
|
||||
/* Copy block to buffer, swapping each 16 bits for Atmel flash */
|
||||
for(i = 0; i < blocksize; i += 4) {
|
||||
uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i));
|
||||
uint32_t word;
|
||||
if (card->atmel_flash)
|
||||
word = swahb32p((uint32_t *)(fw->data + offset + i));
|
||||
else
|
||||
word = *(uint32_t *)(fw->data + offset + i);
|
||||
if(card->fpga_version > LEGACY_BUFFERS)
|
||||
iowrite32(word, FLASH_BUF + i);
|
||||
else
|
||||
@ -961,7 +1085,12 @@ static uint32_t fpga_tx(struct solos_card *card)
|
||||
tx_started |= 1 << port;
|
||||
oldskb = skb; /* We're done with this skb already */
|
||||
} else if (skb && card->using_dma) {
|
||||
SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data,
|
||||
unsigned char *data = skb->data;
|
||||
if ((unsigned long)data & card->dma_alignment) {
|
||||
data = card->dma_bounce + (BUF_SIZE * port);
|
||||
memcpy(data, skb->data, skb->len);
|
||||
}
|
||||
SKB_CB(skb)->dma_addr = pci_map_single(card->dev, data,
|
||||
skb->len, PCI_DMA_TODEVICE);
|
||||
card->tx_skb[port] = skb;
|
||||
iowrite32(SKB_CB(skb)->dma_addr,
|
||||
@ -1133,18 +1262,33 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
db_fpga_upgrade = db_firmware_upgrade = 0;
|
||||
}
|
||||
|
||||
/* Stopped using Atmel flash after 0.03-38 */
|
||||
if (fpga_ver < 39)
|
||||
card->atmel_flash = 1;
|
||||
else
|
||||
card->atmel_flash = 0;
|
||||
|
||||
data32 = ioread32(card->config_regs + PORTS);
|
||||
card->nr_ports = (data32 & 0x000000FF);
|
||||
|
||||
if (card->fpga_version >= DMA_SUPPORTED) {
|
||||
pci_set_master(dev);
|
||||
card->using_dma = 1;
|
||||
if (1) { /* All known FPGA versions so far */
|
||||
card->dma_alignment = 3;
|
||||
card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL);
|
||||
if (!card->dma_bounce) {
|
||||
dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n");
|
||||
/* Fallback to MMIO doesn't work */
|
||||
goto out_unmap_both;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
card->using_dma = 0;
|
||||
/* Set RX empty flag for all ports */
|
||||
iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
|
||||
}
|
||||
|
||||
data32 = ioread32(card->config_regs + PORTS);
|
||||
card->nr_ports = (data32 & 0x000000FF);
|
||||
|
||||
pci_set_drvdata(dev, card);
|
||||
|
||||
tasklet_init(&card->tlet, solos_bh, (unsigned long)card);
|
||||
@ -1179,6 +1323,10 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
if (err)
|
||||
goto out_free_irq;
|
||||
|
||||
if (card->fpga_version >= DMA_SUPPORTED &&
|
||||
sysfs_create_group(&card->dev->dev.kobj, &gpio_attr_group))
|
||||
dev_err(&card->dev->dev, "Could not register parameter group for GPIOs\n");
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_irq:
|
||||
@ -1187,6 +1335,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
tasklet_kill(&card->tlet);
|
||||
|
||||
out_unmap_both:
|
||||
kfree(card->dma_bounce);
|
||||
pci_set_drvdata(dev, NULL);
|
||||
pci_iounmap(dev, card->buffers);
|
||||
out_unmap_config:
|
||||
@ -1289,11 +1438,16 @@ static void fpga_remove(struct pci_dev *dev)
|
||||
iowrite32(1, card->config_regs + FPGA_MODE);
|
||||
(void)ioread32(card->config_regs + FPGA_MODE);
|
||||
|
||||
if (card->fpga_version >= DMA_SUPPORTED)
|
||||
sysfs_remove_group(&card->dev->dev.kobj, &gpio_attr_group);
|
||||
|
||||
atm_remove(card);
|
||||
|
||||
free_irq(dev->irq, card);
|
||||
tasklet_kill(&card->tlet);
|
||||
|
||||
kfree(card->dma_bounce);
|
||||
|
||||
/* Release device from reset */
|
||||
iowrite32(0, card->config_regs + FPGA_MODE);
|
||||
(void)ioread32(card->config_regs + FPGA_MODE);
|
||||
|
@ -1217,8 +1217,7 @@ static void __exit dsp_cleanup(void)
|
||||
{
|
||||
mISDN_unregister_Bprotocol(&DSP);
|
||||
|
||||
if (timer_pending(&dsp_spl_tl))
|
||||
del_timer(&dsp_spl_tl);
|
||||
del_timer_sync(&dsp_spl_tl);
|
||||
|
||||
if (!list_empty(&dsp_ilist)) {
|
||||
printk(KERN_ERR "mISDN_dsp: Audio DSP object inst list not "
|
||||
|
@ -4431,8 +4431,6 @@ static void bond_uninit(struct net_device *bond_dev)
|
||||
|
||||
list_del(&bond->bond_list);
|
||||
|
||||
bond_work_cancel_all(bond);
|
||||
|
||||
bond_debug_unregister(bond);
|
||||
|
||||
__hw_addr_flush(&bond->mc_list);
|
||||
|
@ -121,7 +121,7 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
|
||||
}
|
||||
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
if (irq == NO_IRQ) {
|
||||
if (irq == 0) {
|
||||
dev_err(&ofdev->dev, "no irq found\n");
|
||||
err = -ENODEV;
|
||||
goto exit_unmap_mem;
|
||||
|
@ -616,7 +616,7 @@ static inline bool be_error(struct be_adapter *adapter)
|
||||
return adapter->eeh_error || adapter->hw_error || adapter->fw_timeout;
|
||||
}
|
||||
|
||||
static inline bool be_crit_error(struct be_adapter *adapter)
|
||||
static inline bool be_hw_error(struct be_adapter *adapter)
|
||||
{
|
||||
return adapter->eeh_error || adapter->hw_error;
|
||||
}
|
||||
|
@ -298,7 +298,12 @@ void be_async_mcc_enable(struct be_adapter *adapter)
|
||||
|
||||
void be_async_mcc_disable(struct be_adapter *adapter)
|
||||
{
|
||||
spin_lock_bh(&adapter->mcc_cq_lock);
|
||||
|
||||
adapter->mcc_obj.rearm_cq = false;
|
||||
be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
|
||||
|
||||
spin_unlock_bh(&adapter->mcc_cq_lock);
|
||||
}
|
||||
|
||||
int be_process_mcc(struct be_adapter *adapter)
|
||||
|
@ -1689,15 +1689,41 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo)
|
||||
struct be_queue_info *rxq = &rxo->q;
|
||||
struct be_queue_info *rx_cq = &rxo->cq;
|
||||
struct be_rx_compl_info *rxcp;
|
||||
struct be_adapter *adapter = rxo->adapter;
|
||||
int flush_wait = 0;
|
||||
u16 tail;
|
||||
|
||||
/* First cleanup pending rx completions */
|
||||
while ((rxcp = be_rx_compl_get(rxo)) != NULL) {
|
||||
be_rx_compl_discard(rxo, rxcp);
|
||||
be_cq_notify(rxo->adapter, rx_cq->id, false, 1);
|
||||
/* Consume pending rx completions.
|
||||
* Wait for the flush completion (identified by zero num_rcvd)
|
||||
* to arrive. Notify CQ even when there are no more CQ entries
|
||||
* for HW to flush partially coalesced CQ entries.
|
||||
* In Lancer, there is no need to wait for flush compl.
|
||||
*/
|
||||
for (;;) {
|
||||
rxcp = be_rx_compl_get(rxo);
|
||||
if (rxcp == NULL) {
|
||||
if (lancer_chip(adapter))
|
||||
break;
|
||||
|
||||
if (flush_wait++ > 10 || be_hw_error(adapter)) {
|
||||
dev_warn(&adapter->pdev->dev,
|
||||
"did not receive flush compl\n");
|
||||
break;
|
||||
}
|
||||
be_cq_notify(adapter, rx_cq->id, true, 0);
|
||||
mdelay(1);
|
||||
} else {
|
||||
be_rx_compl_discard(rxo, rxcp);
|
||||
be_cq_notify(adapter, rx_cq->id, true, 1);
|
||||
if (rxcp->num_rcvd == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then free posted rx buffer that were not used */
|
||||
/* After cleanup, leave the CQ in unarmed state */
|
||||
be_cq_notify(adapter, rx_cq->id, false, 0);
|
||||
|
||||
/* Then free posted rx buffers that were not used */
|
||||
tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len;
|
||||
for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) {
|
||||
page_info = get_rx_page_info(rxo, tail);
|
||||
@ -2157,7 +2183,7 @@ void be_detect_error(struct be_adapter *adapter)
|
||||
u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0;
|
||||
u32 i;
|
||||
|
||||
if (be_crit_error(adapter))
|
||||
if (be_hw_error(adapter))
|
||||
return;
|
||||
|
||||
if (lancer_chip(adapter)) {
|
||||
@ -2398,13 +2424,22 @@ static int be_close(struct net_device *netdev)
|
||||
|
||||
be_roce_dev_close(adapter);
|
||||
|
||||
be_async_mcc_disable(adapter);
|
||||
|
||||
if (!lancer_chip(adapter))
|
||||
be_intr_set(adapter, false);
|
||||
|
||||
for_all_evt_queues(adapter, eqo, i) {
|
||||
for_all_evt_queues(adapter, eqo, i)
|
||||
napi_disable(&eqo->napi);
|
||||
|
||||
be_async_mcc_disable(adapter);
|
||||
|
||||
/* Wait for all pending tx completions to arrive so that
|
||||
* all tx skbs are freed.
|
||||
*/
|
||||
be_tx_compl_clean(adapter);
|
||||
|
||||
be_rx_qs_destroy(adapter);
|
||||
|
||||
for_all_evt_queues(adapter, eqo, i) {
|
||||
if (msix_enabled(adapter))
|
||||
synchronize_irq(be_msix_vec_get(adapter, eqo));
|
||||
else
|
||||
@ -2414,12 +2449,6 @@ static int be_close(struct net_device *netdev)
|
||||
|
||||
be_irq_unregister(adapter);
|
||||
|
||||
/* Wait for all pending tx completions to arrive so that
|
||||
* all tx skbs are freed.
|
||||
*/
|
||||
be_tx_compl_clean(adapter);
|
||||
|
||||
be_rx_qs_destroy(adapter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -94,9 +94,8 @@ config GIANFAR
|
||||
|
||||
config FEC_PTP
|
||||
bool "PTP Hardware Clock (PHC)"
|
||||
depends on FEC && ARCH_MXC
|
||||
depends on FEC && ARCH_MXC && !SOC_IMX25 && !SOC_IMX27 && !SOC_IMX35 && !SOC_IMX5
|
||||
select PTP_1588_CLOCK
|
||||
default y if SOC_IMX6Q
|
||||
--help---
|
||||
Say Y here if you want to use PTP Hardware Clock (PHC) in the
|
||||
driver. Only the basic clock operations have been implemented.
|
||||
|
@ -4761,7 +4761,7 @@ static void transmit_cleanup(struct dev_info *hw_priv, int normal)
|
||||
struct ksz_dma_buf *dma_buf;
|
||||
struct net_device *dev = NULL;
|
||||
|
||||
spin_lock(&hw_priv->hwlock);
|
||||
spin_lock_irq(&hw_priv->hwlock);
|
||||
last = info->last;
|
||||
|
||||
while (info->avail < info->alloc) {
|
||||
@ -4795,7 +4795,7 @@ static void transmit_cleanup(struct dev_info *hw_priv, int normal)
|
||||
info->avail++;
|
||||
}
|
||||
info->last = last;
|
||||
spin_unlock(&hw_priv->hwlock);
|
||||
spin_unlock_irq(&hw_priv->hwlock);
|
||||
|
||||
/* Notify the network subsystem that the packet has been sent. */
|
||||
if (dev)
|
||||
@ -5259,11 +5259,15 @@ static irqreturn_t netdev_intr(int irq, void *dev_id)
|
||||
struct dev_info *hw_priv = priv->adapter;
|
||||
struct ksz_hw *hw = &hw_priv->hw;
|
||||
|
||||
spin_lock(&hw_priv->hwlock);
|
||||
|
||||
hw_read_intr(hw, &int_enable);
|
||||
|
||||
/* Not our interrupt! */
|
||||
if (!int_enable)
|
||||
if (!int_enable) {
|
||||
spin_unlock(&hw_priv->hwlock);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
do {
|
||||
hw_ack_intr(hw, int_enable);
|
||||
@ -5310,6 +5314,8 @@ static irqreturn_t netdev_intr(int irq, void *dev_id)
|
||||
|
||||
hw_ena_intr(hw);
|
||||
|
||||
spin_unlock(&hw_priv->hwlock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,8 @@
|
||||
|
||||
#define _QLCNIC_LINUX_MAJOR 5
|
||||
#define _QLCNIC_LINUX_MINOR 0
|
||||
#define _QLCNIC_LINUX_SUBVERSION 29
|
||||
#define QLCNIC_LINUX_VERSIONID "5.0.29"
|
||||
#define _QLCNIC_LINUX_SUBVERSION 30
|
||||
#define QLCNIC_LINUX_VERSIONID "5.0.30"
|
||||
#define QLCNIC_DRV_IDC_VER 0x01
|
||||
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
|
||||
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
|
||||
|
@ -134,7 +134,7 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
|
||||
__le32 *tmp_buf;
|
||||
struct qlcnic_cmd_args cmd;
|
||||
struct qlcnic_hardware_context *ahw;
|
||||
struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl;
|
||||
struct qlcnic_dump_template_hdr *tmpl_hdr;
|
||||
dma_addr_t tmp_addr_t = 0;
|
||||
|
||||
ahw = adapter->ahw;
|
||||
@ -150,6 +150,8 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
|
||||
}
|
||||
temp_size = cmd.rsp.arg2;
|
||||
version = cmd.rsp.arg3;
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"minidump template version = 0x%x", version);
|
||||
if (!temp_size)
|
||||
return -EIO;
|
||||
|
||||
@ -174,7 +176,6 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
|
||||
err = -EIO;
|
||||
goto error;
|
||||
}
|
||||
tmp_tmpl = tmp_addr;
|
||||
ahw->fw_dump.tmpl_hdr = vzalloc(temp_size);
|
||||
if (!ahw->fw_dump.tmpl_hdr) {
|
||||
err = -EIO;
|
||||
|
@ -365,7 +365,7 @@ static int
|
||||
qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
|
||||
struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
|
||||
{
|
||||
u32 i, producer, consumer;
|
||||
u32 i, producer;
|
||||
struct qlcnic_cmd_buffer *pbuf;
|
||||
struct cmd_desc_type0 *cmd_desc;
|
||||
struct qlcnic_host_tx_ring *tx_ring;
|
||||
@ -379,7 +379,6 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
|
||||
__netif_tx_lock_bh(tx_ring->txq);
|
||||
|
||||
producer = tx_ring->producer;
|
||||
consumer = tx_ring->sw_consumer;
|
||||
|
||||
if (nr_desc >= qlcnic_tx_avail(tx_ring)) {
|
||||
netif_tx_stop_queue(tx_ring->txq);
|
||||
@ -402,7 +401,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
|
||||
pbuf->frag_count = 0;
|
||||
|
||||
memcpy(&tx_ring->desc_head[producer],
|
||||
&cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
|
||||
cmd_desc, sizeof(struct cmd_desc_type0));
|
||||
|
||||
producer = get_next_index(producer, tx_ring->num_desc);
|
||||
i++;
|
||||
|
@ -445,13 +445,10 @@ static int
|
||||
qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
u8 id;
|
||||
u32 ref_count;
|
||||
int i, ret = 1;
|
||||
u32 data = QLCNIC_MGMT_FUNC;
|
||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||
|
||||
/* If other drivers are not in use set their privilege level */
|
||||
ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
|
||||
ret = qlcnic_api_lock(adapter);
|
||||
if (ret)
|
||||
goto err_lock;
|
||||
@ -531,11 +528,9 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev,
|
||||
{
|
||||
u32 offset;
|
||||
void __iomem *mem_ptr0 = NULL;
|
||||
resource_size_t mem_base;
|
||||
unsigned long mem_len, pci_len0 = 0, bar0_len;
|
||||
|
||||
/* remap phys address */
|
||||
mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
|
||||
mem_len = pci_resource_len(pdev, 0);
|
||||
|
||||
qlcnic_get_bar_length(pdev->device, &bar0_len);
|
||||
|
@ -197,7 +197,7 @@ static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
|
||||
int i, k, timeout = 0;
|
||||
void __iomem *base = adapter->ahw->pci_base0;
|
||||
u32 addr, data;
|
||||
u8 opcode, no_ops;
|
||||
u8 no_ops;
|
||||
struct __ctrl *ctr = &entry->region.ctrl;
|
||||
struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr;
|
||||
|
||||
@ -206,7 +206,6 @@ static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
|
||||
|
||||
for (i = 0; i < no_ops; i++) {
|
||||
k = 0;
|
||||
opcode = 0;
|
||||
for (k = 0; k < 8; k++) {
|
||||
if (!(ctr->opcode & (1 << k)))
|
||||
continue;
|
||||
|
@ -577,28 +577,30 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
|
||||
{
|
||||
struct net_device *dev = dev_instance;
|
||||
struct cp_private *cp;
|
||||
int handled = 0;
|
||||
u16 status;
|
||||
|
||||
if (unlikely(dev == NULL))
|
||||
return IRQ_NONE;
|
||||
cp = netdev_priv(dev);
|
||||
|
||||
spin_lock(&cp->lock);
|
||||
|
||||
status = cpr16(IntrStatus);
|
||||
if (!status || (status == 0xFFFF))
|
||||
return IRQ_NONE;
|
||||
goto out_unlock;
|
||||
|
||||
handled = 1;
|
||||
|
||||
netif_dbg(cp, intr, dev, "intr, status %04x cmd %02x cpcmd %04x\n",
|
||||
status, cpr8(Cmd), cpr16(CpCmd));
|
||||
|
||||
cpw16(IntrStatus, status & ~cp_rx_intr_mask);
|
||||
|
||||
spin_lock(&cp->lock);
|
||||
|
||||
/* close possible race's with dev_close */
|
||||
if (unlikely(!netif_running(dev))) {
|
||||
cpw16(IntrMask, 0);
|
||||
spin_unlock(&cp->lock);
|
||||
return IRQ_HANDLED;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
|
||||
@ -612,7 +614,6 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
|
||||
if (status & LinkChg)
|
||||
mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
|
||||
|
||||
spin_unlock(&cp->lock);
|
||||
|
||||
if (status & PciErr) {
|
||||
u16 pci_status;
|
||||
@ -625,7 +626,10 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
|
||||
/* TODO: reset hardware */
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
out_unlock:
|
||||
spin_unlock(&cp->lock);
|
||||
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
|
@ -2386,8 +2386,6 @@ static const struct of_device_id smc91x_match[] = {
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, smc91x_match);
|
||||
#else
|
||||
#define smc91x_match NULL
|
||||
#endif
|
||||
|
||||
static struct dev_pm_ops smc_drv_pm_ops = {
|
||||
@ -2402,7 +2400,7 @@ static struct platform_driver smc_driver = {
|
||||
.name = CARDNAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &smc_drv_pm_ops,
|
||||
.of_match_table = smc91x_match,
|
||||
.of_match_table = of_match_ptr(smc91x_match),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -2575,11 +2575,13 @@ static const struct dev_pm_ops smsc911x_pm_ops = {
|
||||
#define SMSC911X_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id smsc911x_dt_ids[] = {
|
||||
{ .compatible = "smsc,lan9115", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, smsc911x_dt_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver smsc911x_driver = {
|
||||
.probe = smsc911x_drv_probe,
|
||||
@ -2588,7 +2590,7 @@ static struct platform_driver smsc911x_driver = {
|
||||
.name = SMSC_CHIPNAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = SMSC911X_PM_OPS,
|
||||
.of_match_table = smsc911x_dt_ids,
|
||||
.of_match_table = of_match_ptr(smsc911x_dt_ids),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -127,14 +127,14 @@ static inline int stmmac_register_platform(void)
|
||||
}
|
||||
static inline void stmmac_unregister_platform(void)
|
||||
{
|
||||
platform_driver_register(&stmmac_pltfr_driver);
|
||||
platform_driver_unregister(&stmmac_pltfr_driver);
|
||||
}
|
||||
#else
|
||||
static inline int stmmac_register_platform(void)
|
||||
{
|
||||
pr_debug("stmmac: do not register the platf driver\n");
|
||||
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
static inline void stmmac_unregister_platform(void)
|
||||
{
|
||||
@ -162,7 +162,7 @@ static inline int stmmac_register_pci(void)
|
||||
{
|
||||
pr_debug("stmmac: do not register the PCI driver\n");
|
||||
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
static inline void stmmac_unregister_pci(void)
|
||||
{
|
||||
|
@ -2194,18 +2194,20 @@ int stmmac_restore(struct net_device *ndev)
|
||||
*/
|
||||
static int __init stmmac_init(void)
|
||||
{
|
||||
int err_plt = 0;
|
||||
int err_pci = 0;
|
||||
|
||||
err_plt = stmmac_register_platform();
|
||||
err_pci = stmmac_register_pci();
|
||||
|
||||
if ((err_pci) && (err_plt)) {
|
||||
pr_err("stmmac: driver registration failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
int ret;
|
||||
|
||||
ret = stmmac_register_platform();
|
||||
if (ret)
|
||||
goto err;
|
||||
ret = stmmac_register_pci();
|
||||
if (ret)
|
||||
goto err_pci;
|
||||
return 0;
|
||||
err_pci:
|
||||
stmmac_unregister_platform();
|
||||
err:
|
||||
pr_err("stmmac: driver registration failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit stmmac_exit(void)
|
||||
|
@ -27,8 +27,6 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
|
||||
#include "cpts.h"
|
||||
|
||||
#ifdef CONFIG_TI_CPTS
|
||||
|
@ -138,6 +138,8 @@ struct tun_file {
|
||||
/* only used for fasnyc */
|
||||
unsigned int flags;
|
||||
u16 queue_index;
|
||||
struct list_head next;
|
||||
struct tun_struct *detached;
|
||||
};
|
||||
|
||||
struct tun_flow_entry {
|
||||
@ -182,6 +184,8 @@ struct tun_struct {
|
||||
struct hlist_head flows[TUN_NUM_FLOW_ENTRIES];
|
||||
struct timer_list flow_gc_timer;
|
||||
unsigned long ageing_time;
|
||||
unsigned int numdisabled;
|
||||
struct list_head disabled;
|
||||
};
|
||||
|
||||
static inline u32 tun_hashfn(u32 rxhash)
|
||||
@ -385,6 +389,23 @@ static void tun_set_real_num_queues(struct tun_struct *tun)
|
||||
netif_set_real_num_rx_queues(tun->dev, tun->numqueues);
|
||||
}
|
||||
|
||||
static void tun_disable_queue(struct tun_struct *tun, struct tun_file *tfile)
|
||||
{
|
||||
tfile->detached = tun;
|
||||
list_add_tail(&tfile->next, &tun->disabled);
|
||||
++tun->numdisabled;
|
||||
}
|
||||
|
||||
static struct tun_struct *tun_enable_queue(struct tun_file *tfile)
|
||||
{
|
||||
struct tun_struct *tun = tfile->detached;
|
||||
|
||||
tfile->detached = NULL;
|
||||
list_del_init(&tfile->next);
|
||||
--tun->numdisabled;
|
||||
return tun;
|
||||
}
|
||||
|
||||
static void __tun_detach(struct tun_file *tfile, bool clean)
|
||||
{
|
||||
struct tun_file *ntfile;
|
||||
@ -406,20 +427,25 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
|
||||
ntfile->queue_index = index;
|
||||
|
||||
--tun->numqueues;
|
||||
sock_put(&tfile->sk);
|
||||
if (clean)
|
||||
sock_put(&tfile->sk);
|
||||
else
|
||||
tun_disable_queue(tun, tfile);
|
||||
|
||||
synchronize_net();
|
||||
tun_flow_delete_by_queue(tun, tun->numqueues + 1);
|
||||
/* Drop read queue */
|
||||
skb_queue_purge(&tfile->sk.sk_receive_queue);
|
||||
tun_set_real_num_queues(tun);
|
||||
|
||||
if (tun->numqueues == 0 && !(tun->flags & TUN_PERSIST))
|
||||
if (dev->reg_state == NETREG_REGISTERED)
|
||||
unregister_netdevice(dev);
|
||||
}
|
||||
} else if (tfile->detached && clean)
|
||||
tun = tun_enable_queue(tfile);
|
||||
|
||||
if (clean) {
|
||||
if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&
|
||||
!(tun->flags & TUN_PERSIST))
|
||||
if (tun->dev->reg_state == NETREG_REGISTERED)
|
||||
unregister_netdevice(tun->dev);
|
||||
|
||||
BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED,
|
||||
&tfile->socket.flags));
|
||||
sk_release_kernel(&tfile->sk);
|
||||
@ -436,7 +462,7 @@ static void tun_detach(struct tun_file *tfile, bool clean)
|
||||
static void tun_detach_all(struct net_device *dev)
|
||||
{
|
||||
struct tun_struct *tun = netdev_priv(dev);
|
||||
struct tun_file *tfile;
|
||||
struct tun_file *tfile, *tmp;
|
||||
int i, n = tun->numqueues;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
@ -457,6 +483,12 @@ static void tun_detach_all(struct net_device *dev)
|
||||
skb_queue_purge(&tfile->sk.sk_receive_queue);
|
||||
sock_put(&tfile->sk);
|
||||
}
|
||||
list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) {
|
||||
tun_enable_queue(tfile);
|
||||
skb_queue_purge(&tfile->sk.sk_receive_queue);
|
||||
sock_put(&tfile->sk);
|
||||
}
|
||||
BUG_ON(tun->numdisabled != 0);
|
||||
}
|
||||
|
||||
static int tun_attach(struct tun_struct *tun, struct file *file)
|
||||
@ -473,7 +505,8 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
|
||||
goto out;
|
||||
|
||||
err = -E2BIG;
|
||||
if (tun->numqueues == MAX_TAP_QUEUES)
|
||||
if (!tfile->detached &&
|
||||
tun->numqueues + tun->numdisabled == MAX_TAP_QUEUES)
|
||||
goto out;
|
||||
|
||||
err = 0;
|
||||
@ -487,9 +520,13 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
|
||||
tfile->queue_index = tun->numqueues;
|
||||
rcu_assign_pointer(tfile->tun, tun);
|
||||
rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
|
||||
sock_hold(&tfile->sk);
|
||||
tun->numqueues++;
|
||||
|
||||
if (tfile->detached)
|
||||
tun_enable_queue(tfile);
|
||||
else
|
||||
sock_hold(&tfile->sk);
|
||||
|
||||
tun_set_real_num_queues(tun);
|
||||
|
||||
/* device is allowed to go away first, so no need to hold extra
|
||||
@ -1162,6 +1199,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
|
||||
}
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
rxhash = skb_get_rxhash(skb);
|
||||
netif_rx_ni(skb);
|
||||
|
||||
@ -1349,6 +1387,7 @@ static void tun_free_netdev(struct net_device *dev)
|
||||
{
|
||||
struct tun_struct *tun = netdev_priv(dev);
|
||||
|
||||
BUG_ON(!(list_empty(&tun->disabled)));
|
||||
tun_flow_uninit(tun);
|
||||
free_netdev(dev);
|
||||
}
|
||||
@ -1543,6 +1582,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
|
||||
err = tun_attach(tun, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tun->flags & TUN_TAP_MQ &&
|
||||
(tun->numqueues + tun->numdisabled > 1))
|
||||
return err;
|
||||
}
|
||||
else {
|
||||
char *name;
|
||||
@ -1601,6 +1644,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
|
||||
TUN_USER_FEATURES;
|
||||
dev->features = dev->hw_features;
|
||||
|
||||
INIT_LIST_HEAD(&tun->disabled);
|
||||
err = tun_attach(tun, file);
|
||||
if (err < 0)
|
||||
goto err_free_dev;
|
||||
@ -1755,32 +1799,28 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
|
||||
{
|
||||
struct tun_file *tfile = file->private_data;
|
||||
struct tun_struct *tun;
|
||||
struct net_device *dev;
|
||||
int ret = 0;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
if (ifr->ifr_flags & IFF_ATTACH_QUEUE) {
|
||||
dev = __dev_get_by_name(tfile->net, ifr->ifr_name);
|
||||
if (!dev) {
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
tun = netdev_priv(dev);
|
||||
if (dev->netdev_ops != &tap_netdev_ops &&
|
||||
dev->netdev_ops != &tun_netdev_ops)
|
||||
tun = tfile->detached;
|
||||
if (!tun)
|
||||
ret = -EINVAL;
|
||||
else if (tun_not_capable(tun))
|
||||
ret = -EPERM;
|
||||
else
|
||||
ret = tun_attach(tun, file);
|
||||
} else if (ifr->ifr_flags & IFF_DETACH_QUEUE)
|
||||
__tun_detach(tfile, false);
|
||||
else
|
||||
} else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
|
||||
tun = rcu_dereference_protected(tfile->tun,
|
||||
lockdep_rtnl_is_held());
|
||||
if (!tun || !(tun->flags & TUN_TAP_MQ))
|
||||
ret = -EINVAL;
|
||||
else
|
||||
__tun_detach(tfile, false);
|
||||
} else
|
||||
ret = -EINVAL;
|
||||
|
||||
unlock:
|
||||
rtnl_unlock();
|
||||
return ret;
|
||||
}
|
||||
@ -2092,6 +2132,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
|
||||
|
||||
file->private_data = tfile;
|
||||
set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags);
|
||||
INIT_LIST_HEAD(&tfile->next);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -457,12 +457,6 @@ int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usbnet_cdc_bind);
|
||||
|
||||
static int cdc_manage_power(struct usbnet *dev, int on)
|
||||
{
|
||||
dev->intf->needs_remote_wakeup = on;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct driver_info cdc_info = {
|
||||
.description = "CDC Ethernet Device",
|
||||
.flags = FLAG_ETHER | FLAG_POINTTOPOINT,
|
||||
@ -470,7 +464,7 @@ static const struct driver_info cdc_info = {
|
||||
.bind = usbnet_cdc_bind,
|
||||
.unbind = usbnet_cdc_unbind,
|
||||
.status = usbnet_cdc_status,
|
||||
.manage_power = cdc_manage_power,
|
||||
.manage_power = usbnet_manage_power,
|
||||
};
|
||||
|
||||
static const struct driver_info wwan_info = {
|
||||
@ -479,7 +473,7 @@ static const struct driver_info wwan_info = {
|
||||
.bind = usbnet_cdc_bind,
|
||||
.unbind = usbnet_cdc_unbind,
|
||||
.status = usbnet_cdc_status,
|
||||
.manage_power = cdc_manage_power,
|
||||
.manage_power = usbnet_manage_power,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -487,6 +481,7 @@ static const struct driver_info wwan_info = {
|
||||
#define HUAWEI_VENDOR_ID 0x12D1
|
||||
#define NOVATEL_VENDOR_ID 0x1410
|
||||
#define ZTE_VENDOR_ID 0x19D2
|
||||
#define DELL_VENDOR_ID 0x413C
|
||||
|
||||
static const struct usb_device_id products [] = {
|
||||
/*
|
||||
@ -594,27 +589,29 @@ static const struct usb_device_id products [] = {
|
||||
|
||||
/* Novatel USB551L and MC551 - handled by qmi_wwan */
|
||||
{
|
||||
.match_flags = USB_DEVICE_ID_MATCH_VENDOR
|
||||
| USB_DEVICE_ID_MATCH_PRODUCT
|
||||
| USB_DEVICE_ID_MATCH_INT_INFO,
|
||||
.idVendor = NOVATEL_VENDOR_ID,
|
||||
.idProduct = 0xB001,
|
||||
.bInterfaceClass = USB_CLASS_COMM,
|
||||
.bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
|
||||
.bInterfaceProtocol = USB_CDC_PROTO_NONE,
|
||||
USB_DEVICE_AND_INTERFACE_INFO(NOVATEL_VENDOR_ID, 0xB001, USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
.driver_info = 0,
|
||||
},
|
||||
|
||||
/* Novatel E362 - handled by qmi_wwan */
|
||||
{
|
||||
.match_flags = USB_DEVICE_ID_MATCH_VENDOR
|
||||
| USB_DEVICE_ID_MATCH_PRODUCT
|
||||
| USB_DEVICE_ID_MATCH_INT_INFO,
|
||||
.idVendor = NOVATEL_VENDOR_ID,
|
||||
.idProduct = 0x9010,
|
||||
.bInterfaceClass = USB_CLASS_COMM,
|
||||
.bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
|
||||
.bInterfaceProtocol = USB_CDC_PROTO_NONE,
|
||||
USB_DEVICE_AND_INTERFACE_INFO(NOVATEL_VENDOR_ID, 0x9010, USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
.driver_info = 0,
|
||||
},
|
||||
|
||||
/* Dell Wireless 5800 (Novatel E362) - handled by qmi_wwan */
|
||||
{
|
||||
USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x8195, USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
.driver_info = 0,
|
||||
},
|
||||
|
||||
/* Dell Wireless 5800 (Novatel E362) - handled by qmi_wwan */
|
||||
{
|
||||
USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x8196, USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
.driver_info = 0,
|
||||
},
|
||||
|
||||
|
@ -1129,19 +1129,13 @@ static void cdc_ncm_disconnect(struct usb_interface *intf)
|
||||
usbnet_disconnect(intf);
|
||||
}
|
||||
|
||||
static int cdc_ncm_manage_power(struct usbnet *dev, int status)
|
||||
{
|
||||
dev->intf->needs_remote_wakeup = status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct driver_info cdc_ncm_info = {
|
||||
.description = "CDC NCM",
|
||||
.flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET,
|
||||
.bind = cdc_ncm_bind,
|
||||
.unbind = cdc_ncm_unbind,
|
||||
.check_connect = cdc_ncm_check_connect,
|
||||
.manage_power = cdc_ncm_manage_power,
|
||||
.manage_power = usbnet_manage_power,
|
||||
.status = cdc_ncm_status,
|
||||
.rx_fixup = cdc_ncm_rx_fixup,
|
||||
.tx_fixup = cdc_ncm_tx_fixup,
|
||||
@ -1155,7 +1149,7 @@ static const struct driver_info wwan_info = {
|
||||
.bind = cdc_ncm_bind,
|
||||
.unbind = cdc_ncm_unbind,
|
||||
.check_connect = cdc_ncm_check_connect,
|
||||
.manage_power = cdc_ncm_manage_power,
|
||||
.manage_power = usbnet_manage_power,
|
||||
.status = cdc_ncm_status,
|
||||
.rx_fixup = cdc_ncm_rx_fixup,
|
||||
.tx_fixup = cdc_ncm_tx_fixup,
|
||||
|
@ -383,6 +383,20 @@ static const struct usb_device_id products[] = {
|
||||
USB_CDC_PROTO_NONE),
|
||||
.driver_info = (unsigned long)&qmi_wwan_info,
|
||||
},
|
||||
{ /* Dell Wireless 5800 (Novatel E362) */
|
||||
USB_DEVICE_AND_INTERFACE_INFO(0x413C, 0x8195,
|
||||
USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET,
|
||||
USB_CDC_PROTO_NONE),
|
||||
.driver_info = (unsigned long)&qmi_wwan_info,
|
||||
},
|
||||
{ /* Dell Wireless 5800 V2 (Novatel E362) */
|
||||
USB_DEVICE_AND_INTERFACE_INFO(0x413C, 0x8196,
|
||||
USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET,
|
||||
USB_CDC_PROTO_NONE),
|
||||
.driver_info = (unsigned long)&qmi_wwan_info,
|
||||
},
|
||||
|
||||
/* 3. Combined interface devices matching on interface number */
|
||||
{QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */
|
||||
@ -419,6 +433,7 @@ static const struct usb_device_id products[] = {
|
||||
{QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */
|
||||
{QMI_FIXED_INTF(0x19d2, 0x0200, 1)},
|
||||
{QMI_FIXED_INTF(0x19d2, 0x0257, 3)}, /* ZTE MF821 */
|
||||
{QMI_FIXED_INTF(0x19d2, 0x0284, 4)}, /* ZTE MF880 */
|
||||
{QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */
|
||||
{QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */
|
||||
{QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */
|
||||
|
@ -719,7 +719,8 @@ int usbnet_stop (struct net_device *net)
|
||||
dev->flags = 0;
|
||||
del_timer_sync (&dev->delay);
|
||||
tasklet_kill (&dev->bh);
|
||||
if (info->manage_power)
|
||||
if (info->manage_power &&
|
||||
!test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags))
|
||||
info->manage_power(dev, 0);
|
||||
else
|
||||
usb_autopm_put_interface(dev->intf);
|
||||
@ -794,14 +795,14 @@ int usbnet_open (struct net_device *net)
|
||||
tasklet_schedule (&dev->bh);
|
||||
if (info->manage_power) {
|
||||
retval = info->manage_power(dev, 1);
|
||||
if (retval < 0)
|
||||
goto done_manage_power_error;
|
||||
usb_autopm_put_interface(dev->intf);
|
||||
if (retval < 0) {
|
||||
retval = 0;
|
||||
set_bit(EVENT_NO_RUNTIME_PM, &dev->flags);
|
||||
} else {
|
||||
usb_autopm_put_interface(dev->intf);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
|
||||
done_manage_power_error:
|
||||
clear_bit(EVENT_DEV_OPEN, &dev->flags);
|
||||
done:
|
||||
usb_autopm_put_interface(dev->intf);
|
||||
done_nopm:
|
||||
@ -1615,6 +1616,16 @@ void usbnet_device_suggests_idle(struct usbnet *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(usbnet_device_suggests_idle);
|
||||
|
||||
/*
|
||||
* For devices that can do without special commands
|
||||
*/
|
||||
int usbnet_manage_power(struct usbnet *dev, int on)
|
||||
{
|
||||
dev->intf->needs_remote_wakeup = on;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(usbnet_manage_power);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
|
||||
u16 value, u16 index, void *data, u16 size)
|
||||
|
@ -152,6 +152,9 @@ enum {
|
||||
/* Device IDs */
|
||||
USB_DEVICE_ID_I6050 = 0x0186,
|
||||
USB_DEVICE_ID_I6050_2 = 0x0188,
|
||||
USB_DEVICE_ID_I6150 = 0x07d6,
|
||||
USB_DEVICE_ID_I6150_2 = 0x07d7,
|
||||
USB_DEVICE_ID_I6150_3 = 0x07d9,
|
||||
USB_DEVICE_ID_I6250 = 0x0187,
|
||||
};
|
||||
|
||||
|
@ -510,6 +510,9 @@ int i2400mu_probe(struct usb_interface *iface,
|
||||
switch (id->idProduct) {
|
||||
case USB_DEVICE_ID_I6050:
|
||||
case USB_DEVICE_ID_I6050_2:
|
||||
case USB_DEVICE_ID_I6150:
|
||||
case USB_DEVICE_ID_I6150_2:
|
||||
case USB_DEVICE_ID_I6150_3:
|
||||
case USB_DEVICE_ID_I6250:
|
||||
i2400mu->i6050 = 1;
|
||||
break;
|
||||
@ -759,6 +762,9 @@ static
|
||||
struct usb_device_id i2400mu_id_table[] = {
|
||||
{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) },
|
||||
{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) },
|
||||
{ USB_DEVICE(0x8087, USB_DEVICE_ID_I6150) },
|
||||
{ USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_2) },
|
||||
{ USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_3) },
|
||||
{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) },
|
||||
{ USB_DEVICE(0x8086, 0x0181) },
|
||||
{ USB_DEVICE(0x8086, 0x1403) },
|
||||
|
@ -47,7 +47,7 @@ obj-$(CONFIG_RT2X00) += rt2x00/
|
||||
|
||||
obj-$(CONFIG_P54_COMMON) += p54/
|
||||
|
||||
obj-$(CONFIG_ATH_COMMON) += ath/
|
||||
obj-$(CONFIG_ATH_CARDS) += ath/
|
||||
|
||||
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
|
||||
|
||||
|
@ -685,6 +685,14 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
|
||||
* to mac80211.
|
||||
*/
|
||||
rx_status = IEEE80211_SKB_RXCB(entry->skb);
|
||||
|
||||
/* Ensure that all fields of rx_status are initialized
|
||||
* properly. The skb->cb array was used for driver
|
||||
* specific informations, so rx_status might contain
|
||||
* garbage.
|
||||
*/
|
||||
memset(rx_status, 0, sizeof(*rx_status));
|
||||
|
||||
rx_status->mactime = rxdesc.timestamp;
|
||||
rx_status->band = rt2x00dev->curr_band;
|
||||
rx_status->freq = rt2x00dev->curr_freq;
|
||||
|
@ -69,6 +69,7 @@ struct usbnet {
|
||||
# define EVENT_DEV_ASLEEP 6
|
||||
# define EVENT_DEV_OPEN 7
|
||||
# define EVENT_DEVICE_REPORT_IDLE 8
|
||||
# define EVENT_NO_RUNTIME_PM 9
|
||||
};
|
||||
|
||||
static inline struct usb_driver *driver_of(struct usb_interface *intf)
|
||||
@ -240,4 +241,6 @@ extern void usbnet_set_msglevel(struct net_device *, u32);
|
||||
extern void usbnet_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
|
||||
extern int usbnet_nway_reset(struct net_device *net);
|
||||
|
||||
extern int usbnet_manage_power(struct usbnet *, int);
|
||||
|
||||
#endif /* __LINUX_USB_USBNET_H */
|
||||
|
@ -318,6 +318,7 @@ extern void inet_csk_reqsk_queue_prune(struct sock *parent,
|
||||
const unsigned long max_rto);
|
||||
|
||||
extern void inet_csk_destroy_sock(struct sock *sk);
|
||||
extern void inet_csk_prepare_forced_close(struct sock *sk);
|
||||
|
||||
/*
|
||||
* LISTEN is a special case for poll..
|
||||
|
@ -78,6 +78,13 @@ struct ra_msg {
|
||||
__be32 retrans_timer;
|
||||
};
|
||||
|
||||
struct rd_msg {
|
||||
struct icmp6hdr icmph;
|
||||
struct in6_addr target;
|
||||
struct in6_addr dest;
|
||||
__u8 opt[0];
|
||||
};
|
||||
|
||||
struct nd_opt_hdr {
|
||||
__u8 nd_opt_type;
|
||||
__u8 nd_opt_len;
|
||||
|
@ -163,6 +163,9 @@ struct br_port_msg {
|
||||
|
||||
struct br_mdb_entry {
|
||||
__u32 ifindex;
|
||||
#define MDB_TEMPORARY 0
|
||||
#define MDB_PERMANENT 1
|
||||
__u8 state;
|
||||
struct {
|
||||
union {
|
||||
__be32 ip4;
|
||||
|
@ -14,49 +14,45 @@ static ssize_t show_type(struct device *cdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct atm_dev *adev = to_atm_dev(cdev);
|
||||
return sprintf(buf, "%s\n", adev->type);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", adev->type);
|
||||
}
|
||||
|
||||
static ssize_t show_address(struct device *cdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
char *pos = buf;
|
||||
struct atm_dev *adev = to_atm_dev(cdev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (ESI_LEN - 1); i++)
|
||||
pos += sprintf(pos, "%02x:", adev->esi[i]);
|
||||
pos += sprintf(pos, "%02x\n", adev->esi[i]);
|
||||
|
||||
return pos - buf;
|
||||
return scnprintf(buf, PAGE_SIZE, "%pM\n", adev->esi);
|
||||
}
|
||||
|
||||
static ssize_t show_atmaddress(struct device *cdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned long flags;
|
||||
char *pos = buf;
|
||||
struct atm_dev *adev = to_atm_dev(cdev);
|
||||
struct atm_dev_addr *aaddr;
|
||||
int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin;
|
||||
int i, j;
|
||||
int i, j, count = 0;
|
||||
|
||||
spin_lock_irqsave(&adev->lock, flags);
|
||||
list_for_each_entry(aaddr, &adev->local, entry) {
|
||||
for (i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) {
|
||||
if (j == *fmt) {
|
||||
pos += sprintf(pos, ".");
|
||||
count += scnprintf(buf + count,
|
||||
PAGE_SIZE - count, ".");
|
||||
++fmt;
|
||||
j = 0;
|
||||
}
|
||||
pos += sprintf(pos, "%02x",
|
||||
aaddr->addr.sas_addr.prv[i]);
|
||||
count += scnprintf(buf + count,
|
||||
PAGE_SIZE - count, "%02x",
|
||||
aaddr->addr.sas_addr.prv[i]);
|
||||
}
|
||||
pos += sprintf(pos, "\n");
|
||||
count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
|
||||
}
|
||||
spin_unlock_irqrestore(&adev->lock, flags);
|
||||
|
||||
return pos - buf;
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_atmindex(struct device *cdev,
|
||||
@ -64,25 +60,21 @@ static ssize_t show_atmindex(struct device *cdev,
|
||||
{
|
||||
struct atm_dev *adev = to_atm_dev(cdev);
|
||||
|
||||
return sprintf(buf, "%d\n", adev->number);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", adev->number);
|
||||
}
|
||||
|
||||
static ssize_t show_carrier(struct device *cdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
char *pos = buf;
|
||||
struct atm_dev *adev = to_atm_dev(cdev);
|
||||
|
||||
pos += sprintf(pos, "%d\n",
|
||||
adev->signal == ATM_PHY_SIG_LOST ? 0 : 1);
|
||||
|
||||
return pos - buf;
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
adev->signal == ATM_PHY_SIG_LOST ? 0 : 1);
|
||||
}
|
||||
|
||||
static ssize_t show_link_rate(struct device *cdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
char *pos = buf;
|
||||
struct atm_dev *adev = to_atm_dev(cdev);
|
||||
int link_rate;
|
||||
|
||||
@ -100,9 +92,7 @@ static ssize_t show_link_rate(struct device *cdev,
|
||||
default:
|
||||
link_rate = adev->link_rate * 8 * 53;
|
||||
}
|
||||
pos += sprintf(pos, "%d\n", link_rate);
|
||||
|
||||
return pos - buf;
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", link_rate);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
|
||||
|
@ -83,9 +83,12 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
|
||||
if (port) {
|
||||
struct br_mdb_entry e;
|
||||
e.ifindex = port->dev->ifindex;
|
||||
e.addr.u.ip4 = p->addr.u.ip4;
|
||||
e.state = p->state;
|
||||
if (p->addr.proto == htons(ETH_P_IP))
|
||||
e.addr.u.ip4 = p->addr.u.ip4;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
e.addr.u.ip6 = p->addr.u.ip6;
|
||||
if (p->addr.proto == htons(ETH_P_IPV6))
|
||||
e.addr.u.ip6 = p->addr.u.ip6;
|
||||
#endif
|
||||
e.addr.proto = p->addr.proto;
|
||||
if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(e), &e)) {
|
||||
@ -253,6 +256,8 @@ static bool is_valid_mdb_entry(struct br_mdb_entry *entry)
|
||||
#endif
|
||||
} else
|
||||
return false;
|
||||
if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -310,7 +315,7 @@ static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
}
|
||||
|
||||
static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
|
||||
struct br_ip *group)
|
||||
struct br_ip *group, unsigned char state)
|
||||
{
|
||||
struct net_bridge_mdb_entry *mp;
|
||||
struct net_bridge_port_group *p;
|
||||
@ -336,7 +341,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
|
||||
break;
|
||||
}
|
||||
|
||||
p = br_multicast_new_port_group(port, group, *pp);
|
||||
p = br_multicast_new_port_group(port, group, *pp, state);
|
||||
if (unlikely(!p))
|
||||
return -ENOMEM;
|
||||
rcu_assign_pointer(*pp, p);
|
||||
@ -373,7 +378,7 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br,
|
||||
#endif
|
||||
|
||||
spin_lock_bh(&br->multicast_lock);
|
||||
ret = br_mdb_add_group(br, p, &ip);
|
||||
ret = br_mdb_add_group(br, p, &ip, entry->state);
|
||||
spin_unlock_bh(&br->multicast_lock);
|
||||
return ret;
|
||||
}
|
||||
@ -479,3 +484,10 @@ void br_mdb_init(void)
|
||||
rtnl_register(PF_BRIDGE, RTM_NEWMDB, br_mdb_add, NULL, NULL);
|
||||
rtnl_register(PF_BRIDGE, RTM_DELMDB, br_mdb_del, NULL, NULL);
|
||||
}
|
||||
|
||||
void br_mdb_uninit(void)
|
||||
{
|
||||
rtnl_unregister(PF_BRIDGE, RTM_GETMDB);
|
||||
rtnl_unregister(PF_BRIDGE, RTM_NEWMDB);
|
||||
rtnl_unregister(PF_BRIDGE, RTM_DELMDB);
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ static void br_multicast_port_group_expired(unsigned long data)
|
||||
|
||||
spin_lock(&br->multicast_lock);
|
||||
if (!netif_running(br->dev) || timer_pending(&pg->timer) ||
|
||||
hlist_unhashed(&pg->mglist))
|
||||
hlist_unhashed(&pg->mglist) || pg->state & MDB_PERMANENT)
|
||||
goto out;
|
||||
|
||||
br_multicast_del_pg(br, pg);
|
||||
@ -622,7 +622,8 @@ out:
|
||||
struct net_bridge_port_group *br_multicast_new_port_group(
|
||||
struct net_bridge_port *port,
|
||||
struct br_ip *group,
|
||||
struct net_bridge_port_group __rcu *next)
|
||||
struct net_bridge_port_group __rcu *next,
|
||||
unsigned char state)
|
||||
{
|
||||
struct net_bridge_port_group *p;
|
||||
|
||||
@ -632,6 +633,7 @@ struct net_bridge_port_group *br_multicast_new_port_group(
|
||||
|
||||
p->addr = *group;
|
||||
p->port = port;
|
||||
p->state = state;
|
||||
rcu_assign_pointer(p->next, next);
|
||||
hlist_add_head(&p->mglist, &port->mglist);
|
||||
setup_timer(&p->timer, br_multicast_port_group_expired,
|
||||
@ -674,7 +676,7 @@ static int br_multicast_add_group(struct net_bridge *br,
|
||||
break;
|
||||
}
|
||||
|
||||
p = br_multicast_new_port_group(port, group, *pp);
|
||||
p = br_multicast_new_port_group(port, group, *pp, MDB_TEMPORARY);
|
||||
if (unlikely(!p))
|
||||
goto err;
|
||||
rcu_assign_pointer(*pp, p);
|
||||
@ -1165,7 +1167,6 @@ static int br_ip6_multicast_query(struct net_bridge *br,
|
||||
if (max_delay)
|
||||
group = &mld->mld_mca;
|
||||
} else if (skb->len >= sizeof(*mld2q)) {
|
||||
u16 mrc;
|
||||
if (!pskb_may_pull(skb, sizeof(*mld2q))) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
@ -1173,8 +1174,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
|
||||
mld2q = (struct mld2_query *)icmp6_hdr(skb);
|
||||
if (!mld2q->mld2q_nsrcs)
|
||||
group = &mld2q->mld2q_mca;
|
||||
mrc = ntohs(mld2q->mld2q_mrc);
|
||||
max_delay = mrc ? MLDV2_MRC(mrc) : 1;
|
||||
max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(ntohs(mld2q->mld2q_mrc)) : 1;
|
||||
}
|
||||
|
||||
if (!group)
|
||||
@ -1633,6 +1633,7 @@ void br_multicast_stop(struct net_bridge *br)
|
||||
del_timer_sync(&br->multicast_querier_timer);
|
||||
del_timer_sync(&br->multicast_query_timer);
|
||||
|
||||
br_mdb_uninit();
|
||||
spin_lock_bh(&br->multicast_lock);
|
||||
mdb = mlock_dereference(br->mdb, br);
|
||||
if (!mdb)
|
||||
|
@ -305,5 +305,4 @@ int __init br_netlink_init(void)
|
||||
void __exit br_netlink_fini(void)
|
||||
{
|
||||
rtnl_link_unregister(&br_link_ops);
|
||||
rtnl_unregister_all(PF_BRIDGE);
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ struct net_bridge_port_group {
|
||||
struct rcu_head rcu;
|
||||
struct timer_list timer;
|
||||
struct br_ip addr;
|
||||
unsigned char state;
|
||||
};
|
||||
|
||||
struct net_bridge_mdb_entry
|
||||
@ -443,8 +444,10 @@ extern void br_multicast_free_pg(struct rcu_head *head);
|
||||
extern struct net_bridge_port_group *br_multicast_new_port_group(
|
||||
struct net_bridge_port *port,
|
||||
struct br_ip *group,
|
||||
struct net_bridge_port_group *next);
|
||||
struct net_bridge_port_group *next,
|
||||
unsigned char state);
|
||||
extern void br_mdb_init(void);
|
||||
extern void br_mdb_uninit(void);
|
||||
extern void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
|
||||
struct br_ip *group, int type);
|
||||
|
||||
|
@ -439,8 +439,8 @@ exit:
|
||||
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
|
||||
return NULL;
|
||||
put_and_exit:
|
||||
bh_unlock_sock(newsk);
|
||||
sock_put(newsk);
|
||||
inet_csk_prepare_forced_close(newsk);
|
||||
dccp_done(newsk);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -585,7 +585,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
|
||||
newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
|
||||
|
||||
if (__inet_inherit_port(sk, newsk) < 0) {
|
||||
sock_put(newsk);
|
||||
inet_csk_prepare_forced_close(newsk);
|
||||
dccp_done(newsk);
|
||||
goto out;
|
||||
}
|
||||
__inet6_hash(newsk, NULL);
|
||||
|
@ -710,6 +710,22 @@ void inet_csk_destroy_sock(struct sock *sk)
|
||||
}
|
||||
EXPORT_SYMBOL(inet_csk_destroy_sock);
|
||||
|
||||
/* This function allows to force a closure of a socket after the call to
|
||||
* tcp/dccp_create_openreq_child().
|
||||
*/
|
||||
void inet_csk_prepare_forced_close(struct sock *sk)
|
||||
{
|
||||
/* sk_clone_lock locked the socket and set refcnt to 2 */
|
||||
bh_unlock_sock(sk);
|
||||
sock_put(sk);
|
||||
|
||||
/* The below has to be done to allow calling inet_csk_destroy_sock */
|
||||
sock_set_flag(sk, SOCK_DEAD);
|
||||
percpu_counter_inc(sk->sk_prot->orphan_count);
|
||||
inet_sk(sk)->inet_num = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(inet_csk_prepare_forced_close);
|
||||
|
||||
int inet_csk_listen_start(struct sock *sk, const int nr_table_entries)
|
||||
{
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
|
@ -1767,10 +1767,8 @@ exit:
|
||||
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
|
||||
return NULL;
|
||||
put_and_exit:
|
||||
tcp_clear_xmit_timers(newsk);
|
||||
tcp_cleanup_congestion_control(newsk);
|
||||
bh_unlock_sock(newsk);
|
||||
sock_put(newsk);
|
||||
inet_csk_prepare_forced_close(newsk);
|
||||
tcp_done(newsk);
|
||||
goto exit;
|
||||
}
|
||||
EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
|
||||
|
@ -41,6 +41,6 @@ obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
|
||||
obj-$(CONFIG_IPV6_GRE) += ip6_gre.o
|
||||
|
||||
obj-y += addrconf_core.o exthdrs_core.o
|
||||
obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6_offload)
|
||||
obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload)
|
||||
|
||||
obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
|
||||
|
@ -534,8 +534,7 @@ void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
|
||||
rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_ATOMIC);
|
||||
return;
|
||||
errout:
|
||||
if (err < 0)
|
||||
rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err);
|
||||
rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err);
|
||||
}
|
||||
|
||||
static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
|
||||
|
@ -1314,6 +1314,12 @@ out:
|
||||
|
||||
static void ndisc_redirect_rcv(struct sk_buff *skb)
|
||||
{
|
||||
u8 *hdr;
|
||||
struct ndisc_options ndopts;
|
||||
struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb);
|
||||
u32 ndoptlen = skb->tail - (skb->transport_header +
|
||||
offsetof(struct rd_msg, opt));
|
||||
|
||||
#ifdef CONFIG_IPV6_NDISC_NODETYPE
|
||||
switch (skb->ndisc_nodetype) {
|
||||
case NDISC_NODETYPE_HOST:
|
||||
@ -1330,6 +1336,17 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts))
|
||||
return;
|
||||
|
||||
if (!ndopts.nd_opts_rh)
|
||||
return;
|
||||
|
||||
hdr = (u8 *)ndopts.nd_opts_rh;
|
||||
hdr += 8;
|
||||
if (!pskb_pull(skb, hdr - skb_transport_header(skb)))
|
||||
return;
|
||||
|
||||
icmpv6_notify(skb, NDISC_REDIRECT, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -1288,7 +1288,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
|
||||
#endif
|
||||
|
||||
if (__inet_inherit_port(sk, newsk) < 0) {
|
||||
sock_put(newsk);
|
||||
inet_csk_prepare_forced_close(newsk);
|
||||
tcp_done(newsk);
|
||||
goto out;
|
||||
}
|
||||
__inet6_hash(newsk, NULL);
|
||||
|
@ -224,9 +224,9 @@ void ieee802154_free_device(struct ieee802154_dev *hw)
|
||||
|
||||
BUG_ON(!list_empty(&priv->slaves));
|
||||
|
||||
wpan_phy_free(priv->phy);
|
||||
|
||||
mutex_destroy(&priv->slaves_mtx);
|
||||
|
||||
wpan_phy_free(priv->phy);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee802154_free_device);
|
||||
|
||||
|
@ -669,6 +669,9 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
|
||||
struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
|
||||
int err;
|
||||
|
||||
if (addr_len < sizeof(struct sockaddr_nl))
|
||||
return -EINVAL;
|
||||
|
||||
if (nladdr->nl_family != AF_NETLINK)
|
||||
return -EINVAL;
|
||||
|
||||
@ -2059,7 +2062,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
|
||||
struct sock *s = v;
|
||||
struct netlink_sock *nlk = nlk_sk(s);
|
||||
|
||||
seq_printf(seq, "%pK %-3d %-6d %08x %-8d %-8d %pK %-8d %-8d %-8lu\n",
|
||||
seq_printf(seq, "%pK %-3d %-6u %08x %-8d %-8d %pK %-8d %-8d %-8lu\n",
|
||||
s,
|
||||
s->sk_protocol,
|
||||
nlk->portid,
|
||||
|
@ -66,12 +66,36 @@ config SCTP_DBG_OBJCNT
|
||||
'cat /proc/net/sctp/sctp_dbg_objcnt'
|
||||
|
||||
If unsure, say N
|
||||
choice
|
||||
prompt "Default SCTP cookie HMAC encoding"
|
||||
default SCTP_COOKIE_HMAC_MD5
|
||||
help
|
||||
This option sets the default sctp cookie hmac algorithm
|
||||
when in doubt select 'md5'
|
||||
|
||||
config SCTP_DEFAULT_COOKIE_HMAC_MD5
|
||||
bool "Enable optional MD5 hmac cookie generation"
|
||||
help
|
||||
Enable optional MD5 hmac based SCTP cookie generation
|
||||
select SCTP_COOKIE_HMAC_MD5
|
||||
|
||||
config SCTP_DEFAULT_COOKIE_HMAC_SHA1
|
||||
bool "Enable optional SHA1 hmac cookie generation"
|
||||
help
|
||||
Enable optional SHA1 hmac based SCTP cookie generation
|
||||
select SCTP_COOKIE_HMAC_SHA1
|
||||
|
||||
config SCTP_DEFAULT_COOKIE_HMAC_NONE
|
||||
bool "Use no hmac alg in SCTP cookie generation"
|
||||
help
|
||||
Use no hmac algorithm in SCTP cookie generation
|
||||
|
||||
endchoice
|
||||
|
||||
config SCTP_COOKIE_HMAC_MD5
|
||||
bool "Enable optional MD5 hmac cookie generation"
|
||||
help
|
||||
Enable optional MD5 hmac based SCTP cookie generation
|
||||
default y
|
||||
select CRYPTO_HMAC if SCTP_COOKIE_HMAC_MD5
|
||||
select CRYPTO_MD5 if SCTP_COOKIE_HMAC_MD5
|
||||
|
||||
@ -79,7 +103,6 @@ config SCTP_COOKIE_HMAC_SHA1
|
||||
bool "Enable optional SHA1 hmac cookie generation"
|
||||
help
|
||||
Enable optional SHA1 hmac based SCTP cookie generation
|
||||
default y
|
||||
select CRYPTO_HMAC if SCTP_COOKIE_HMAC_SHA1
|
||||
select CRYPTO_SHA1 if SCTP_COOKIE_HMAC_SHA1
|
||||
|
||||
|
@ -122,7 +122,8 @@ static const struct file_operations sctpprobe_fops = {
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
|
||||
sctp_disposition_t jsctp_sf_eat_sack(const struct sctp_endpoint *ep,
|
||||
sctp_disposition_t jsctp_sf_eat_sack(struct net *net,
|
||||
const struct sctp_endpoint *ep,
|
||||
const struct sctp_association *asoc,
|
||||
const sctp_subtype_t type,
|
||||
void *arg,
|
||||
|
@ -1191,9 +1191,9 @@ static int __net_init sctp_net_init(struct net *net)
|
||||
net->sctp.cookie_preserve_enable = 1;
|
||||
|
||||
/* Default sctp sockets to use md5 as their hmac alg */
|
||||
#if defined (CONFIG_CRYPTO_MD5)
|
||||
#if defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5)
|
||||
net->sctp.sctp_hmac_alg = "md5";
|
||||
#elif defined (CONFIG_CRYPTO_SHA1)
|
||||
#elif defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1)
|
||||
net->sctp.sctp_hmac_alg = "sha1";
|
||||
#else
|
||||
net->sctp.sctp_hmac_alg = NULL;
|
||||
|
@ -69,6 +69,8 @@ static struct nlmsg_perm nlmsg_route_perms[] =
|
||||
{ RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_NEWNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_NEWMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_DELMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETMDB, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user