diff options
32 files changed, 374 insertions, 192 deletions
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 8a3054b84812..5de74e762021 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c | |||
@@ -325,6 +325,9 @@ static int ldisc_open(struct tty_struct *tty) | |||
325 | 325 | ||
326 | sprintf(name, "cf%s", tty->name); | 326 | sprintf(name, "cf%s", tty->name); |
327 | dev = alloc_netdev(sizeof(*ser), name, caifdev_setup); | 327 | dev = alloc_netdev(sizeof(*ser), name, caifdev_setup); |
328 | if (!dev) | ||
329 | return -ENOMEM; | ||
330 | |||
328 | ser = netdev_priv(dev); | 331 | ser = netdev_priv(dev); |
329 | ser->tty = tty_kref_get(tty); | 332 | ser->tty = tty_kref_get(tty); |
330 | ser->dev = dev; | 333 | ser->dev = dev; |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index ec62a5c8bd37..28a0bcfe61ff 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h | |||
@@ -1603,6 +1603,10 @@ | |||
1603 | * of counts that the SM entered the EEE LPI state. Clock 25MHz. Read only | 1603 | * of counts that the SM entered the EEE LPI state. Clock 25MHz. Read only |
1604 | * register. Reset on hard reset. */ | 1604 | * register. Reset on hard reset. */ |
1605 | #define MISC_REG_CPMU_LP_SM_ENT_CNT_P0 0xa8b8 | 1605 | #define MISC_REG_CPMU_LP_SM_ENT_CNT_P0 0xa8b8 |
1606 | /* [RW 16] EEE LPI Entry Events Counter. A statistic counter with the number | ||
1607 | * of counts that the SM entered the EEE LPI state. Clock 25MHz. Read only | ||
1608 | * register. Reset on hard reset. */ | ||
1609 | #define MISC_REG_CPMU_LP_SM_ENT_CNT_P1 0xa8bc | ||
1606 | /* [RW 32] The following driver registers(1...16) represent 16 drivers and | 1610 | /* [RW 32] The following driver registers(1...16) represent 16 drivers and |
1607 | 32 clients. Each client can be controlled by one driver only. One in each | 1611 | 32 clients. Each client can be controlled by one driver only. One in each |
1608 | bit represent that this driver control the appropriate client (Ex: bit 5 | 1612 | bit represent that this driver control the appropriate client (Ex: bit 5 |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index 667d89042d35..332db64dd5be 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c | |||
@@ -785,9 +785,11 @@ static int bnx2x_hw_stats_update(struct bnx2x *bp) | |||
785 | 785 | ||
786 | pstats->host_port_stats_counter++; | 786 | pstats->host_port_stats_counter++; |
787 | 787 | ||
788 | if (CHIP_IS_E3(bp)) | 788 | if (CHIP_IS_E3(bp)) { |
789 | estats->eee_tx_lpi += REG_RD(bp, | 789 | u32 lpi_reg = BP_PORT(bp) ? MISC_REG_CPMU_LP_SM_ENT_CNT_P1 |
790 | MISC_REG_CPMU_LP_SM_ENT_CNT_P0); | 790 | : MISC_REG_CPMU_LP_SM_ENT_CNT_P0; |
791 | estats->eee_tx_lpi += REG_RD(bp, lpi_reg); | ||
792 | } | ||
791 | 793 | ||
792 | if (!BP_NOMCP(bp)) { | 794 | if (!BP_NOMCP(bp)) { |
793 | u32 nig_timer_max = | 795 | u32 nig_timer_max = |
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index e34be1c7ae8a..c0e700653f96 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c | |||
@@ -910,8 +910,9 @@ static void be_set_fw_log_level(struct be_adapter *adapter, u32 level) | |||
910 | if (!status) { | 910 | if (!status) { |
911 | cfgs = (struct be_fat_conf_params *)(extfat_cmd.va + | 911 | cfgs = (struct be_fat_conf_params *)(extfat_cmd.va + |
912 | sizeof(struct be_cmd_resp_hdr)); | 912 | sizeof(struct be_cmd_resp_hdr)); |
913 | for (i = 0; i < cfgs->num_modules; i++) { | 913 | for (i = 0; i < le32_to_cpu(cfgs->num_modules); i++) { |
914 | for (j = 0; j < cfgs->module[i].num_modes; j++) { | 914 | u32 num_modes = le32_to_cpu(cfgs->module[i].num_modes); |
915 | for (j = 0; j < num_modes; j++) { | ||
915 | if (cfgs->module[i].trace_lvl[j].mode == | 916 | if (cfgs->module[i].trace_lvl[j].mode == |
916 | MODE_UART) | 917 | MODE_UART) |
917 | cfgs->module[i].trace_lvl[j].dbg_lvl = | 918 | cfgs->module[i].trace_lvl[j].dbg_lvl = |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 4d9677174490..c60de89b6669 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -1397,7 +1397,7 @@ static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl, | |||
1397 | rxcp->pkt_type = | 1397 | rxcp->pkt_type = |
1398 | AMAP_GET_BITS(struct amap_eth_rx_compl_v1, cast_enc, compl); | 1398 | AMAP_GET_BITS(struct amap_eth_rx_compl_v1, cast_enc, compl); |
1399 | rxcp->rss_hash = | 1399 | rxcp->rss_hash = |
1400 | AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, rxcp); | 1400 | AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, compl); |
1401 | if (rxcp->vlanf) { | 1401 | if (rxcp->vlanf) { |
1402 | rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, | 1402 | rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, |
1403 | compl); | 1403 | compl); |
@@ -1429,7 +1429,7 @@ static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl, | |||
1429 | rxcp->pkt_type = | 1429 | rxcp->pkt_type = |
1430 | AMAP_GET_BITS(struct amap_eth_rx_compl_v0, cast_enc, compl); | 1430 | AMAP_GET_BITS(struct amap_eth_rx_compl_v0, cast_enc, compl); |
1431 | rxcp->rss_hash = | 1431 | rxcp->rss_hash = |
1432 | AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, rxcp); | 1432 | AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, compl); |
1433 | if (rxcp->vlanf) { | 1433 | if (rxcp->vlanf) { |
1434 | rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, | 1434 | rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, |
1435 | compl); | 1435 | compl); |
@@ -3579,7 +3579,7 @@ u32 be_get_fw_log_level(struct be_adapter *adapter) | |||
3579 | if (!status) { | 3579 | if (!status) { |
3580 | cfgs = (struct be_fat_conf_params *)(extfat_cmd.va + | 3580 | cfgs = (struct be_fat_conf_params *)(extfat_cmd.va + |
3581 | sizeof(struct be_cmd_resp_hdr)); | 3581 | sizeof(struct be_cmd_resp_hdr)); |
3582 | for (j = 0; j < cfgs->module[0].num_modes; j++) { | 3582 | for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) { |
3583 | if (cfgs->module[0].trace_lvl[j].mode == MODE_UART) | 3583 | if (cfgs->module[0].trace_lvl[j].mode == MODE_UART) |
3584 | level = cfgs->module[0].trace_lvl[j].dbg_lvl; | 3584 | level = cfgs->module[0].trace_lvl[j].dbg_lvl; |
3585 | } | 3585 | } |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 3b6784cf134a..c709eae58c63 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -396,11 +396,10 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter) | |||
396 | pr_cont("\n"); | 396 | pr_cont("\n"); |
397 | 397 | ||
398 | if (netif_msg_pktdata(adapter) && | 398 | if (netif_msg_pktdata(adapter) && |
399 | dma_unmap_len(tx_buffer, len) != 0) | 399 | tx_buffer->skb) |
400 | print_hex_dump(KERN_INFO, "", | 400 | print_hex_dump(KERN_INFO, "", |
401 | DUMP_PREFIX_ADDRESS, 16, 1, | 401 | DUMP_PREFIX_ADDRESS, 16, 1, |
402 | phys_to_virt(dma_unmap_addr(tx_buffer, | 402 | tx_buffer->skb->data, |
403 | dma)), | ||
404 | dma_unmap_len(tx_buffer, len), | 403 | dma_unmap_len(tx_buffer, len), |
405 | true); | 404 | true); |
406 | } | 405 | } |
@@ -474,10 +473,12 @@ rx_ring_summary: | |||
474 | (u64)rx_buffer_info->dma, | 473 | (u64)rx_buffer_info->dma, |
475 | rx_buffer_info->skb); | 474 | rx_buffer_info->skb); |
476 | 475 | ||
477 | if (netif_msg_pktdata(adapter)) { | 476 | if (netif_msg_pktdata(adapter) && |
477 | rx_buffer_info->dma) { | ||
478 | print_hex_dump(KERN_INFO, "", | 478 | print_hex_dump(KERN_INFO, "", |
479 | DUMP_PREFIX_ADDRESS, 16, 1, | 479 | DUMP_PREFIX_ADDRESS, 16, 1, |
480 | phys_to_virt(rx_buffer_info->dma), | 480 | page_address(rx_buffer_info->page) + |
481 | rx_buffer_info->page_offset, | ||
481 | ixgbe_rx_bufsz(rx_ring), true); | 482 | ixgbe_rx_bufsz(rx_ring), true); |
482 | } | 483 | } |
483 | } | 484 | } |
diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c index 915e947b422d..9c656fe4983d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/catas.c +++ b/drivers/net/ethernet/mellanox/mlx4/catas.c | |||
@@ -69,16 +69,21 @@ static void poll_catas(unsigned long dev_ptr) | |||
69 | struct mlx4_priv *priv = mlx4_priv(dev); | 69 | struct mlx4_priv *priv = mlx4_priv(dev); |
70 | 70 | ||
71 | if (readl(priv->catas_err.map)) { | 71 | if (readl(priv->catas_err.map)) { |
72 | dump_err_buf(dev); | 72 | /* If the device is off-line, we cannot try to recover it */ |
73 | 73 | if (pci_channel_offline(dev->pdev)) | |
74 | mlx4_dispatch_event(dev, MLX4_DEV_EVENT_CATASTROPHIC_ERROR, 0); | 74 | mod_timer(&priv->catas_err.timer, |
75 | round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL)); | ||
76 | else { | ||
77 | dump_err_buf(dev); | ||
78 | mlx4_dispatch_event(dev, MLX4_DEV_EVENT_CATASTROPHIC_ERROR, 0); | ||
75 | 79 | ||
76 | if (internal_err_reset) { | 80 | if (internal_err_reset) { |
77 | spin_lock(&catas_lock); | 81 | spin_lock(&catas_lock); |
78 | list_add(&priv->catas_err.list, &catas_list); | 82 | list_add(&priv->catas_err.list, &catas_list); |
79 | spin_unlock(&catas_lock); | 83 | spin_unlock(&catas_lock); |
80 | 84 | ||
81 | queue_work(mlx4_wq, &catas_work); | 85 | queue_work(mlx4_wq, &catas_work); |
86 | } | ||
82 | } | 87 | } |
83 | } else | 88 | } else |
84 | mod_timer(&priv->catas_err.timer, | 89 | mod_timer(&priv->catas_err.timer, |
@@ -100,6 +105,10 @@ static void catas_reset(struct work_struct *work) | |||
100 | list_for_each_entry_safe(priv, tmppriv, &tlist, catas_err.list) { | 105 | list_for_each_entry_safe(priv, tmppriv, &tlist, catas_err.list) { |
101 | struct pci_dev *pdev = priv->dev.pdev; | 106 | struct pci_dev *pdev = priv->dev.pdev; |
102 | 107 | ||
108 | /* If the device is off-line, we cannot reset it */ | ||
109 | if (pci_channel_offline(pdev)) | ||
110 | continue; | ||
111 | |||
103 | ret = mlx4_restart_one(priv->dev.pdev); | 112 | ret = mlx4_restart_one(priv->dev.pdev); |
104 | /* 'priv' now is not valid */ | 113 | /* 'priv' now is not valid */ |
105 | if (ret) | 114 | if (ret) |
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 7e94987d030c..c8fef4353021 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c | |||
@@ -296,7 +296,12 @@ int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param, | |||
296 | 296 | ||
297 | static int cmd_pending(struct mlx4_dev *dev) | 297 | static int cmd_pending(struct mlx4_dev *dev) |
298 | { | 298 | { |
299 | u32 status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET); | 299 | u32 status; |
300 | |||
301 | if (pci_channel_offline(dev->pdev)) | ||
302 | return -EIO; | ||
303 | |||
304 | status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET); | ||
300 | 305 | ||
301 | return (status & swab32(1 << HCR_GO_BIT)) || | 306 | return (status & swab32(1 << HCR_GO_BIT)) || |
302 | (mlx4_priv(dev)->cmd.toggle == | 307 | (mlx4_priv(dev)->cmd.toggle == |
@@ -314,11 +319,29 @@ static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param, | |||
314 | 319 | ||
315 | mutex_lock(&cmd->hcr_mutex); | 320 | mutex_lock(&cmd->hcr_mutex); |
316 | 321 | ||
322 | if (pci_channel_offline(dev->pdev)) { | ||
323 | /* | ||
324 | * Device is going through error recovery | ||
325 | * and cannot accept commands. | ||
326 | */ | ||
327 | ret = -EIO; | ||
328 | goto out; | ||
329 | } | ||
330 | |||
317 | end = jiffies; | 331 | end = jiffies; |
318 | if (event) | 332 | if (event) |
319 | end += msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS); | 333 | end += msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS); |
320 | 334 | ||
321 | while (cmd_pending(dev)) { | 335 | while (cmd_pending(dev)) { |
336 | if (pci_channel_offline(dev->pdev)) { | ||
337 | /* | ||
338 | * Device is going through error recovery | ||
339 | * and cannot accept commands. | ||
340 | */ | ||
341 | ret = -EIO; | ||
342 | goto out; | ||
343 | } | ||
344 | |||
322 | if (time_after_eq(jiffies, end)) { | 345 | if (time_after_eq(jiffies, end)) { |
323 | mlx4_err(dev, "%s:cmd_pending failed\n", __func__); | 346 | mlx4_err(dev, "%s:cmd_pending failed\n", __func__); |
324 | goto out; | 347 | goto out; |
@@ -431,14 +454,33 @@ static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param, | |||
431 | 454 | ||
432 | down(&priv->cmd.poll_sem); | 455 | down(&priv->cmd.poll_sem); |
433 | 456 | ||
457 | if (pci_channel_offline(dev->pdev)) { | ||
458 | /* | ||
459 | * Device is going through error recovery | ||
460 | * and cannot accept commands. | ||
461 | */ | ||
462 | err = -EIO; | ||
463 | goto out; | ||
464 | } | ||
465 | |||
434 | err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0, | 466 | err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0, |
435 | in_modifier, op_modifier, op, CMD_POLL_TOKEN, 0); | 467 | in_modifier, op_modifier, op, CMD_POLL_TOKEN, 0); |
436 | if (err) | 468 | if (err) |
437 | goto out; | 469 | goto out; |
438 | 470 | ||
439 | end = msecs_to_jiffies(timeout) + jiffies; | 471 | end = msecs_to_jiffies(timeout) + jiffies; |
440 | while (cmd_pending(dev) && time_before(jiffies, end)) | 472 | while (cmd_pending(dev) && time_before(jiffies, end)) { |
473 | if (pci_channel_offline(dev->pdev)) { | ||
474 | /* | ||
475 | * Device is going through error recovery | ||
476 | * and cannot accept commands. | ||
477 | */ | ||
478 | err = -EIO; | ||
479 | goto out; | ||
480 | } | ||
481 | |||
441 | cond_resched(); | 482 | cond_resched(); |
483 | } | ||
442 | 484 | ||
443 | if (cmd_pending(dev)) { | 485 | if (cmd_pending(dev)) { |
444 | err = -ETIMEDOUT; | 486 | err = -ETIMEDOUT; |
@@ -532,6 +574,9 @@ int __mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, | |||
532 | int out_is_imm, u32 in_modifier, u8 op_modifier, | 574 | int out_is_imm, u32 in_modifier, u8 op_modifier, |
533 | u16 op, unsigned long timeout, int native) | 575 | u16 op, unsigned long timeout, int native) |
534 | { | 576 | { |
577 | if (pci_channel_offline(dev->pdev)) | ||
578 | return -EIO; | ||
579 | |||
535 | if (!mlx4_is_mfunc(dev) || (native && mlx4_is_master(dev))) { | 580 | if (!mlx4_is_mfunc(dev) || (native && mlx4_is_master(dev))) { |
536 | if (mlx4_priv(dev)->cmd.use_events) | 581 | if (mlx4_priv(dev)->cmd.use_events) |
537 | return mlx4_cmd_wait(dev, in_param, out_param, | 582 | return mlx4_cmd_wait(dev, in_param, out_param, |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 8864d8b53737..edd9cb8d3e1d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
@@ -201,7 +201,7 @@ mlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip, | |||
201 | 201 | ||
202 | filter->flow_id = flow_id; | 202 | filter->flow_id = flow_id; |
203 | 203 | ||
204 | filter->id = priv->last_filter_id++; | 204 | filter->id = priv->last_filter_id++ % RPS_NO_FILTER; |
205 | 205 | ||
206 | list_add_tail(&filter->next, &priv->filters); | 206 | list_add_tail(&filter->next, &priv->filters); |
207 | hlist_add_head(&filter->filter_chain, | 207 | hlist_add_head(&filter->filter_chain, |
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index e8f8ebb4ae65..48d0e90194cb 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -1817,6 +1817,9 @@ static int mlx4_get_ownership(struct mlx4_dev *dev) | |||
1817 | void __iomem *owner; | 1817 | void __iomem *owner; |
1818 | u32 ret; | 1818 | u32 ret; |
1819 | 1819 | ||
1820 | if (pci_channel_offline(dev->pdev)) | ||
1821 | return -EIO; | ||
1822 | |||
1820 | owner = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_OWNER_BASE, | 1823 | owner = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_OWNER_BASE, |
1821 | MLX4_OWNER_SIZE); | 1824 | MLX4_OWNER_SIZE); |
1822 | if (!owner) { | 1825 | if (!owner) { |
@@ -1833,6 +1836,9 @@ static void mlx4_free_ownership(struct mlx4_dev *dev) | |||
1833 | { | 1836 | { |
1834 | void __iomem *owner; | 1837 | void __iomem *owner; |
1835 | 1838 | ||
1839 | if (pci_channel_offline(dev->pdev)) | ||
1840 | return; | ||
1841 | |||
1836 | owner = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_OWNER_BASE, | 1842 | owner = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_OWNER_BASE, |
1837 | MLX4_OWNER_SIZE); | 1843 | MLX4_OWNER_SIZE); |
1838 | if (!owner) { | 1844 | if (!owner) { |
@@ -2279,11 +2285,33 @@ static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = { | |||
2279 | 2285 | ||
2280 | MODULE_DEVICE_TABLE(pci, mlx4_pci_table); | 2286 | MODULE_DEVICE_TABLE(pci, mlx4_pci_table); |
2281 | 2287 | ||
2288 | static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev, | ||
2289 | pci_channel_state_t state) | ||
2290 | { | ||
2291 | mlx4_remove_one(pdev); | ||
2292 | |||
2293 | return state == pci_channel_io_perm_failure ? | ||
2294 | PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; | ||
2295 | } | ||
2296 | |||
2297 | static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev) | ||
2298 | { | ||
2299 | int ret = __mlx4_init_one(pdev, NULL); | ||
2300 | |||
2301 | return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; | ||
2302 | } | ||
2303 | |||
2304 | static struct pci_error_handlers mlx4_err_handler = { | ||
2305 | .error_detected = mlx4_pci_err_detected, | ||
2306 | .slot_reset = mlx4_pci_slot_reset, | ||
2307 | }; | ||
2308 | |||
2282 | static struct pci_driver mlx4_driver = { | 2309 | static struct pci_driver mlx4_driver = { |
2283 | .name = DRV_NAME, | 2310 | .name = DRV_NAME, |
2284 | .id_table = mlx4_pci_table, | 2311 | .id_table = mlx4_pci_table, |
2285 | .probe = mlx4_init_one, | 2312 | .probe = mlx4_init_one, |
2286 | .remove = __devexit_p(mlx4_remove_one) | 2313 | .remove = __devexit_p(mlx4_remove_one), |
2314 | .err_handler = &mlx4_err_handler, | ||
2287 | }; | 2315 | }; |
2288 | 2316 | ||
2289 | static int __init mlx4_verify_params(void) | 2317 | static int __init mlx4_verify_params(void) |
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c index 9dbf38c10a68..24b787be6062 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c | |||
@@ -129,7 +129,6 @@ static int pch_gbe_set_settings(struct net_device *netdev, | |||
129 | hw->mac.link_duplex = ecmd->duplex; | 129 | hw->mac.link_duplex = ecmd->duplex; |
130 | hw->phy.autoneg_advertised = ecmd->advertising; | 130 | hw->phy.autoneg_advertised = ecmd->advertising; |
131 | hw->mac.autoneg = ecmd->autoneg; | 131 | hw->mac.autoneg = ecmd->autoneg; |
132 | pch_gbe_hal_phy_sw_reset(hw); | ||
133 | 132 | ||
134 | /* reset the link */ | 133 | /* reset the link */ |
135 | if (netif_running(adapter->netdev)) { | 134 | if (netif_running(adapter->netdev)) { |
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index b1006563f736..feb85d56c750 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/ptp_classify.h> | 26 | #include <linux/ptp_classify.h> |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | #define DRV_VERSION "1.00" | 29 | #define DRV_VERSION "1.01" |
30 | const char pch_driver_version[] = DRV_VERSION; | 30 | const char pch_driver_version[] = DRV_VERSION; |
31 | 31 | ||
32 | #define PCI_DEVICE_ID_INTEL_IOH1_GBE 0x8802 /* Pci device ID */ | 32 | #define PCI_DEVICE_ID_INTEL_IOH1_GBE 0x8802 /* Pci device ID */ |
@@ -35,7 +35,7 @@ const char pch_driver_version[] = DRV_VERSION; | |||
35 | #define DSC_INIT16 0xC000 | 35 | #define DSC_INIT16 0xC000 |
36 | #define PCH_GBE_DMA_ALIGN 0 | 36 | #define PCH_GBE_DMA_ALIGN 0 |
37 | #define PCH_GBE_DMA_PADDING 2 | 37 | #define PCH_GBE_DMA_PADDING 2 |
38 | #define PCH_GBE_WATCHDOG_PERIOD (1 * HZ) /* watchdog time */ | 38 | #define PCH_GBE_WATCHDOG_PERIOD (5 * HZ) /* watchdog time */ |
39 | #define PCH_GBE_COPYBREAK_DEFAULT 256 | 39 | #define PCH_GBE_COPYBREAK_DEFAULT 256 |
40 | #define PCH_GBE_PCI_BAR 1 | 40 | #define PCH_GBE_PCI_BAR 1 |
41 | #define PCH_GBE_RESERVE_MEMORY 0x200000 /* 2MB */ | 41 | #define PCH_GBE_RESERVE_MEMORY 0x200000 /* 2MB */ |
@@ -1579,7 +1579,8 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, | |||
1579 | struct sk_buff *skb; | 1579 | struct sk_buff *skb; |
1580 | unsigned int i; | 1580 | unsigned int i; |
1581 | unsigned int cleaned_count = 0; | 1581 | unsigned int cleaned_count = 0; |
1582 | bool cleaned = true; | 1582 | bool cleaned = false; |
1583 | int unused, thresh; | ||
1583 | 1584 | ||
1584 | pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean); | 1585 | pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean); |
1585 | 1586 | ||
@@ -1588,10 +1589,36 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, | |||
1588 | pr_debug("gbec_status:0x%04x dma_status:0x%04x\n", | 1589 | pr_debug("gbec_status:0x%04x dma_status:0x%04x\n", |
1589 | tx_desc->gbec_status, tx_desc->dma_status); | 1590 | tx_desc->gbec_status, tx_desc->dma_status); |
1590 | 1591 | ||
1592 | unused = PCH_GBE_DESC_UNUSED(tx_ring); | ||
1593 | thresh = tx_ring->count - PCH_GBE_TX_WEIGHT; | ||
1594 | if ((tx_desc->gbec_status == DSC_INIT16) && (unused < thresh)) | ||
1595 | { /* current marked clean, tx queue filling up, do extra clean */ | ||
1596 | int j, k; | ||
1597 | if (unused < 8) { /* tx queue nearly full */ | ||
1598 | pr_debug("clean_tx: transmit queue warning (%x,%x) unused=%d\n", | ||
1599 | tx_ring->next_to_clean,tx_ring->next_to_use,unused); | ||
1600 | } | ||
1601 | |||
1602 | /* current marked clean, scan for more that need cleaning. */ | ||
1603 | k = i; | ||
1604 | for (j = 0; j < PCH_GBE_TX_WEIGHT; j++) | ||
1605 | { | ||
1606 | tx_desc = PCH_GBE_TX_DESC(*tx_ring, k); | ||
1607 | if (tx_desc->gbec_status != DSC_INIT16) break; /*found*/ | ||
1608 | if (++k >= tx_ring->count) k = 0; /*increment, wrap*/ | ||
1609 | } | ||
1610 | if (j < PCH_GBE_TX_WEIGHT) { | ||
1611 | pr_debug("clean_tx: unused=%d loops=%d found tx_desc[%x,%x:%x].gbec_status=%04x\n", | ||
1612 | unused,j, i,k, tx_ring->next_to_use, tx_desc->gbec_status); | ||
1613 | i = k; /*found one to clean, usu gbec_status==2000.*/ | ||
1614 | } | ||
1615 | } | ||
1616 | |||
1591 | while ((tx_desc->gbec_status & DSC_INIT16) == 0x0000) { | 1617 | while ((tx_desc->gbec_status & DSC_INIT16) == 0x0000) { |
1592 | pr_debug("gbec_status:0x%04x\n", tx_desc->gbec_status); | 1618 | pr_debug("gbec_status:0x%04x\n", tx_desc->gbec_status); |
1593 | buffer_info = &tx_ring->buffer_info[i]; | 1619 | buffer_info = &tx_ring->buffer_info[i]; |
1594 | skb = buffer_info->skb; | 1620 | skb = buffer_info->skb; |
1621 | cleaned = true; | ||
1595 | 1622 | ||
1596 | if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_ABT)) { | 1623 | if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_ABT)) { |
1597 | adapter->stats.tx_aborted_errors++; | 1624 | adapter->stats.tx_aborted_errors++; |
@@ -1639,18 +1666,21 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, | |||
1639 | } | 1666 | } |
1640 | pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n", | 1667 | pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n", |
1641 | cleaned_count); | 1668 | cleaned_count); |
1642 | /* Recover from running out of Tx resources in xmit_frame */ | 1669 | if (cleaned_count > 0) { /*skip this if nothing cleaned*/ |
1643 | spin_lock(&tx_ring->tx_lock); | 1670 | /* Recover from running out of Tx resources in xmit_frame */ |
1644 | if (unlikely(cleaned && (netif_queue_stopped(adapter->netdev)))) { | 1671 | spin_lock(&tx_ring->tx_lock); |
1645 | netif_wake_queue(adapter->netdev); | 1672 | if (unlikely(cleaned && (netif_queue_stopped(adapter->netdev)))) |
1646 | adapter->stats.tx_restart_count++; | 1673 | { |
1647 | pr_debug("Tx wake queue\n"); | 1674 | netif_wake_queue(adapter->netdev); |
1648 | } | 1675 | adapter->stats.tx_restart_count++; |
1676 | pr_debug("Tx wake queue\n"); | ||
1677 | } | ||
1649 | 1678 | ||
1650 | tx_ring->next_to_clean = i; | 1679 | tx_ring->next_to_clean = i; |
1651 | 1680 | ||
1652 | pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean); | 1681 | pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean); |
1653 | spin_unlock(&tx_ring->tx_lock); | 1682 | spin_unlock(&tx_ring->tx_lock); |
1683 | } | ||
1654 | return cleaned; | 1684 | return cleaned; |
1655 | } | 1685 | } |
1656 | 1686 | ||
@@ -1988,6 +2018,7 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) | |||
1988 | void pch_gbe_down(struct pch_gbe_adapter *adapter) | 2018 | void pch_gbe_down(struct pch_gbe_adapter *adapter) |
1989 | { | 2019 | { |
1990 | struct net_device *netdev = adapter->netdev; | 2020 | struct net_device *netdev = adapter->netdev; |
2021 | struct pci_dev *pdev = adapter->pdev; | ||
1991 | struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring; | 2022 | struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring; |
1992 | 2023 | ||
1993 | /* signal that we're down so the interrupt handler does not | 2024 | /* signal that we're down so the interrupt handler does not |
@@ -2004,7 +2035,8 @@ void pch_gbe_down(struct pch_gbe_adapter *adapter) | |||
2004 | netif_carrier_off(netdev); | 2035 | netif_carrier_off(netdev); |
2005 | netif_stop_queue(netdev); | 2036 | netif_stop_queue(netdev); |
2006 | 2037 | ||
2007 | pch_gbe_reset(adapter); | 2038 | if ((pdev->error_state) && (pdev->error_state != pci_channel_io_normal)) |
2039 | pch_gbe_reset(adapter); | ||
2008 | pch_gbe_clean_tx_ring(adapter, adapter->tx_ring); | 2040 | pch_gbe_clean_tx_ring(adapter, adapter->tx_ring); |
2009 | pch_gbe_clean_rx_ring(adapter, adapter->rx_ring); | 2041 | pch_gbe_clean_rx_ring(adapter, adapter->rx_ring); |
2010 | 2042 | ||
@@ -2127,13 +2159,6 @@ static int pch_gbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
2127 | struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring; | 2159 | struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring; |
2128 | unsigned long flags; | 2160 | unsigned long flags; |
2129 | 2161 | ||
2130 | if (unlikely(skb->len > (adapter->hw.mac.max_frame_size - 4))) { | ||
2131 | pr_err("Transfer length Error: skb len: %d > max: %d\n", | ||
2132 | skb->len, adapter->hw.mac.max_frame_size); | ||
2133 | dev_kfree_skb_any(skb); | ||
2134 | adapter->stats.tx_length_errors++; | ||
2135 | return NETDEV_TX_OK; | ||
2136 | } | ||
2137 | if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) { | 2162 | if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) { |
2138 | /* Collision - tell upper layer to requeue */ | 2163 | /* Collision - tell upper layer to requeue */ |
2139 | return NETDEV_TX_LOCKED; | 2164 | return NETDEV_TX_LOCKED; |
@@ -2387,7 +2412,7 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) | |||
2387 | pch_gbe_clean_rx(adapter, adapter->rx_ring, &work_done, budget); | 2412 | pch_gbe_clean_rx(adapter, adapter->rx_ring, &work_done, budget); |
2388 | cleaned = pch_gbe_clean_tx(adapter, adapter->tx_ring); | 2413 | cleaned = pch_gbe_clean_tx(adapter, adapter->tx_ring); |
2389 | 2414 | ||
2390 | if (!cleaned) | 2415 | if (cleaned) |
2391 | work_done = budget; | 2416 | work_done = budget; |
2392 | /* If no Tx and not enough Rx work done, | 2417 | /* If no Tx and not enough Rx work done, |
2393 | * exit the polling mode | 2418 | * exit the polling mode |
@@ -2793,6 +2818,7 @@ static int __init pch_gbe_init_module(void) | |||
2793 | { | 2818 | { |
2794 | int ret; | 2819 | int ret; |
2795 | 2820 | ||
2821 | pr_info("EG20T PCH Gigabit Ethernet Driver - version %s\n",DRV_VERSION); | ||
2796 | ret = pci_register_driver(&pch_gbe_driver); | 2822 | ret = pci_register_driver(&pch_gbe_driver); |
2797 | if (copybreak != PCH_GBE_COPYBREAK_DEFAULT) { | 2823 | if (copybreak != PCH_GBE_COPYBREAK_DEFAULT) { |
2798 | if (copybreak == 0) { | 2824 | if (copybreak == 0) { |
diff --git a/drivers/net/ethernet/wiznet/Kconfig b/drivers/net/ethernet/wiznet/Kconfig index cb18043f5830..b4d281626fb4 100644 --- a/drivers/net/ethernet/wiznet/Kconfig +++ b/drivers/net/ethernet/wiznet/Kconfig | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | config NET_VENDOR_WIZNET | 5 | config NET_VENDOR_WIZNET |
6 | bool "WIZnet devices" | 6 | bool "WIZnet devices" |
7 | depends on HAS_IOMEM | ||
7 | default y | 8 | default y |
8 | ---help--- | 9 | ---help--- |
9 | If you have a network (Ethernet) card belonging to this class, say Y | 10 | If you have a network (Ethernet) card belonging to this class, say Y |
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 8e23c084c4a7..8c5a1c43c81d 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c | |||
@@ -47,7 +47,7 @@ struct net_device_context { | |||
47 | struct work_struct work; | 47 | struct work_struct work; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | 50 | #define RING_SIZE_MIN 64 | |
51 | static int ring_size = 128; | 51 | static int ring_size = 128; |
52 | module_param(ring_size, int, S_IRUGO); | 52 | module_param(ring_size, int, S_IRUGO); |
53 | MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); | 53 | MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); |
@@ -518,6 +518,11 @@ static void __exit netvsc_drv_exit(void) | |||
518 | 518 | ||
519 | static int __init netvsc_drv_init(void) | 519 | static int __init netvsc_drv_init(void) |
520 | { | 520 | { |
521 | if (ring_size < RING_SIZE_MIN) { | ||
522 | ring_size = RING_SIZE_MIN; | ||
523 | pr_info("Increased ring_size to %d (min allowed)\n", | ||
524 | ring_size); | ||
525 | } | ||
521 | return vmbus_driver_register(&netvsc_drv); | 526 | return vmbus_driver_register(&netvsc_drv); |
522 | } | 527 | } |
523 | 528 | ||
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index fbf539468205..e5d6146937fa 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c | |||
@@ -804,18 +804,15 @@ int rndis_filter_device_add(struct hv_device *dev, | |||
804 | /* Send the rndis initialization message */ | 804 | /* Send the rndis initialization message */ |
805 | ret = rndis_filter_init_device(rndis_device); | 805 | ret = rndis_filter_init_device(rndis_device); |
806 | if (ret != 0) { | 806 | if (ret != 0) { |
807 | /* | 807 | rndis_filter_device_remove(dev); |
808 | * TODO: If rndis init failed, we will need to shut down the | 808 | return ret; |
809 | * channel | ||
810 | */ | ||
811 | } | 809 | } |
812 | 810 | ||
813 | /* Get the mac address */ | 811 | /* Get the mac address */ |
814 | ret = rndis_filter_query_device_mac(rndis_device); | 812 | ret = rndis_filter_query_device_mac(rndis_device); |
815 | if (ret != 0) { | 813 | if (ret != 0) { |
816 | /* | 814 | rndis_filter_device_remove(dev); |
817 | * TODO: shutdown rndis device and the channel | 815 | return ret; |
818 | */ | ||
819 | } | 816 | } |
820 | 817 | ||
821 | memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN); | 818 | memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN); |
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index b104c05225f7..87707ab39430 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c | |||
@@ -1447,7 +1447,7 @@ static int team_netpoll_setup(struct net_device *dev, | |||
1447 | { | 1447 | { |
1448 | struct team *team = netdev_priv(dev); | 1448 | struct team *team = netdev_priv(dev); |
1449 | struct team_port *port; | 1449 | struct team_port *port; |
1450 | int err; | 1450 | int err = 0; |
1451 | 1451 | ||
1452 | mutex_lock(&team->lock); | 1452 | mutex_lock(&team->lock); |
1453 | list_for_each_entry(port, &team->port_list, list) { | 1453 | list_for_each_entry(port, &team->port_list, list) { |
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4b9513fcf275..f4ce5957df32 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c | |||
@@ -138,20 +138,7 @@ struct cdc_ncm_ctx { | |||
138 | static void cdc_ncm_txpath_bh(unsigned long param); | 138 | static void cdc_ncm_txpath_bh(unsigned long param); |
139 | static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx); | 139 | static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx); |
140 | static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer); | 140 | static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer); |
141 | static const struct driver_info cdc_ncm_info; | ||
142 | static struct usb_driver cdc_ncm_driver; | 141 | static struct usb_driver cdc_ncm_driver; |
143 | static const struct ethtool_ops cdc_ncm_ethtool_ops; | ||
144 | |||
145 | static const struct usb_device_id cdc_devs[] = { | ||
146 | { USB_INTERFACE_INFO(USB_CLASS_COMM, | ||
147 | USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), | ||
148 | .driver_info = (unsigned long)&cdc_ncm_info, | ||
149 | }, | ||
150 | { | ||
151 | }, | ||
152 | }; | ||
153 | |||
154 | MODULE_DEVICE_TABLE(usb, cdc_devs); | ||
155 | 142 | ||
156 | static void | 143 | static void |
157 | cdc_ncm_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) | 144 | cdc_ncm_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) |
@@ -454,6 +441,16 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx) | |||
454 | kfree(ctx); | 441 | kfree(ctx); |
455 | } | 442 | } |
456 | 443 | ||
444 | static const struct ethtool_ops cdc_ncm_ethtool_ops = { | ||
445 | .get_drvinfo = cdc_ncm_get_drvinfo, | ||
446 | .get_link = usbnet_get_link, | ||
447 | .get_msglevel = usbnet_get_msglevel, | ||
448 | .set_msglevel = usbnet_set_msglevel, | ||
449 | .get_settings = usbnet_get_settings, | ||
450 | .set_settings = usbnet_set_settings, | ||
451 | .nway_reset = usbnet_nway_reset, | ||
452 | }; | ||
453 | |||
457 | static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) | 454 | static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) |
458 | { | 455 | { |
459 | struct cdc_ncm_ctx *ctx; | 456 | struct cdc_ncm_ctx *ctx; |
@@ -1203,6 +1200,41 @@ static const struct driver_info cdc_ncm_info = { | |||
1203 | .tx_fixup = cdc_ncm_tx_fixup, | 1200 | .tx_fixup = cdc_ncm_tx_fixup, |
1204 | }; | 1201 | }; |
1205 | 1202 | ||
1203 | /* Same as cdc_ncm_info, but with FLAG_WWAN */ | ||
1204 | static const struct driver_info wwan_info = { | ||
1205 | .description = "Mobile Broadband Network Device", | ||
1206 | .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET | ||
1207 | | FLAG_WWAN, | ||
1208 | .bind = cdc_ncm_bind, | ||
1209 | .unbind = cdc_ncm_unbind, | ||
1210 | .check_connect = cdc_ncm_check_connect, | ||
1211 | .manage_power = cdc_ncm_manage_power, | ||
1212 | .status = cdc_ncm_status, | ||
1213 | .rx_fixup = cdc_ncm_rx_fixup, | ||
1214 | .tx_fixup = cdc_ncm_tx_fixup, | ||
1215 | }; | ||
1216 | |||
1217 | static const struct usb_device_id cdc_devs[] = { | ||
1218 | /* Ericsson MBM devices like F5521gw */ | ||
1219 | { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | ||
1220 | | USB_DEVICE_ID_MATCH_VENDOR, | ||
1221 | .idVendor = 0x0bdb, | ||
1222 | .bInterfaceClass = USB_CLASS_COMM, | ||
1223 | .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, | ||
1224 | .bInterfaceProtocol = USB_CDC_PROTO_NONE, | ||
1225 | .driver_info = (unsigned long) &wwan_info, | ||
1226 | }, | ||
1227 | |||
1228 | /* Generic CDC-NCM devices */ | ||
1229 | { USB_INTERFACE_INFO(USB_CLASS_COMM, | ||
1230 | USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), | ||
1231 | .driver_info = (unsigned long)&cdc_ncm_info, | ||
1232 | }, | ||
1233 | { | ||
1234 | }, | ||
1235 | }; | ||
1236 | MODULE_DEVICE_TABLE(usb, cdc_devs); | ||
1237 | |||
1206 | static struct usb_driver cdc_ncm_driver = { | 1238 | static struct usb_driver cdc_ncm_driver = { |
1207 | .name = "cdc_ncm", | 1239 | .name = "cdc_ncm", |
1208 | .id_table = cdc_devs, | 1240 | .id_table = cdc_devs, |
@@ -1215,16 +1247,6 @@ static struct usb_driver cdc_ncm_driver = { | |||
1215 | .disable_hub_initiated_lpm = 1, | 1247 | .disable_hub_initiated_lpm = 1, |
1216 | }; | 1248 | }; |
1217 | 1249 | ||
1218 | static const struct ethtool_ops cdc_ncm_ethtool_ops = { | ||
1219 | .get_drvinfo = cdc_ncm_get_drvinfo, | ||
1220 | .get_link = usbnet_get_link, | ||
1221 | .get_msglevel = usbnet_get_msglevel, | ||
1222 | .set_msglevel = usbnet_set_msglevel, | ||
1223 | .get_settings = usbnet_get_settings, | ||
1224 | .set_settings = usbnet_set_settings, | ||
1225 | .nway_reset = usbnet_nway_reset, | ||
1226 | }; | ||
1227 | |||
1228 | module_usb_driver(cdc_ncm_driver); | 1250 | module_usb_driver(cdc_ncm_driver); |
1229 | 1251 | ||
1230 | MODULE_AUTHOR("Hans Petter Selasky"); | 1252 | MODULE_AUTHOR("Hans Petter Selasky"); |
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 8160591913f9..4ffa66c87ea5 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c | |||
@@ -1854,26 +1854,11 @@ static struct attribute_group netiucv_stat_attr_group = { | |||
1854 | .attrs = netiucv_stat_attrs, | 1854 | .attrs = netiucv_stat_attrs, |
1855 | }; | 1855 | }; |
1856 | 1856 | ||
1857 | static int netiucv_add_files(struct device *dev) | 1857 | static const struct attribute_group *netiucv_attr_groups[] = { |
1858 | { | 1858 | &netiucv_stat_attr_group, |
1859 | int ret; | 1859 | &netiucv_attr_group, |
1860 | 1860 | NULL, | |
1861 | IUCV_DBF_TEXT(trace, 3, __func__); | 1861 | }; |
1862 | ret = sysfs_create_group(&dev->kobj, &netiucv_attr_group); | ||
1863 | if (ret) | ||
1864 | return ret; | ||
1865 | ret = sysfs_create_group(&dev->kobj, &netiucv_stat_attr_group); | ||
1866 | if (ret) | ||
1867 | sysfs_remove_group(&dev->kobj, &netiucv_attr_group); | ||
1868 | return ret; | ||
1869 | } | ||
1870 | |||
1871 | static void netiucv_remove_files(struct device *dev) | ||
1872 | { | ||
1873 | IUCV_DBF_TEXT(trace, 3, __func__); | ||
1874 | sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group); | ||
1875 | sysfs_remove_group(&dev->kobj, &netiucv_attr_group); | ||
1876 | } | ||
1877 | 1862 | ||
1878 | static int netiucv_register_device(struct net_device *ndev) | 1863 | static int netiucv_register_device(struct net_device *ndev) |
1879 | { | 1864 | { |
@@ -1887,6 +1872,7 @@ static int netiucv_register_device(struct net_device *ndev) | |||
1887 | dev_set_name(dev, "net%s", ndev->name); | 1872 | dev_set_name(dev, "net%s", ndev->name); |
1888 | dev->bus = &iucv_bus; | 1873 | dev->bus = &iucv_bus; |
1889 | dev->parent = iucv_root; | 1874 | dev->parent = iucv_root; |
1875 | dev->groups = netiucv_attr_groups; | ||
1890 | /* | 1876 | /* |
1891 | * The release function could be called after the | 1877 | * The release function could be called after the |
1892 | * module has been unloaded. It's _only_ task is to | 1878 | * module has been unloaded. It's _only_ task is to |
@@ -1904,22 +1890,14 @@ static int netiucv_register_device(struct net_device *ndev) | |||
1904 | put_device(dev); | 1890 | put_device(dev); |
1905 | return ret; | 1891 | return ret; |
1906 | } | 1892 | } |
1907 | ret = netiucv_add_files(dev); | ||
1908 | if (ret) | ||
1909 | goto out_unreg; | ||
1910 | priv->dev = dev; | 1893 | priv->dev = dev; |
1911 | dev_set_drvdata(dev, priv); | 1894 | dev_set_drvdata(dev, priv); |
1912 | return 0; | 1895 | return 0; |
1913 | |||
1914 | out_unreg: | ||
1915 | device_unregister(dev); | ||
1916 | return ret; | ||
1917 | } | 1896 | } |
1918 | 1897 | ||
1919 | static void netiucv_unregister_device(struct device *dev) | 1898 | static void netiucv_unregister_device(struct device *dev) |
1920 | { | 1899 | { |
1921 | IUCV_DBF_TEXT(trace, 3, __func__); | 1900 | IUCV_DBF_TEXT(trace, 3, __func__); |
1922 | netiucv_remove_files(dev); | ||
1923 | device_unregister(dev); | 1901 | device_unregister(dev); |
1924 | } | 1902 | } |
1925 | 1903 | ||
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 0cf706699a04..c5f03fa70fba 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -1758,6 +1758,8 @@ static void qeth_l3_free_vlan_addresses4(struct qeth_card *card, | |||
1758 | QETH_CARD_TEXT(card, 4, "frvaddr4"); | 1758 | QETH_CARD_TEXT(card, 4, "frvaddr4"); |
1759 | 1759 | ||
1760 | netdev = __vlan_find_dev_deep(card->dev, vid); | 1760 | netdev = __vlan_find_dev_deep(card->dev, vid); |
1761 | if (!netdev) | ||
1762 | return; | ||
1761 | in_dev = in_dev_get(netdev); | 1763 | in_dev = in_dev_get(netdev); |
1762 | if (!in_dev) | 1764 | if (!in_dev) |
1763 | return; | 1765 | return; |
@@ -1786,6 +1788,8 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card, | |||
1786 | QETH_CARD_TEXT(card, 4, "frvaddr6"); | 1788 | QETH_CARD_TEXT(card, 4, "frvaddr6"); |
1787 | 1789 | ||
1788 | netdev = __vlan_find_dev_deep(card->dev, vid); | 1790 | netdev = __vlan_find_dev_deep(card->dev, vid); |
1791 | if (!netdev) | ||
1792 | return; | ||
1789 | in6_dev = in6_dev_get(netdev); | 1793 | in6_dev = in6_dev_get(netdev); |
1790 | if (!in6_dev) | 1794 | if (!in6_dev) |
1791 | return; | 1795 | return; |
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 00cbb4384c79..9e34c877a770 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h | |||
@@ -96,14 +96,15 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo, | |||
96 | const __be16 sport, | 96 | const __be16 sport, |
97 | const __be16 dport) | 97 | const __be16 dport) |
98 | { | 98 | { |
99 | struct sock *sk; | 99 | struct sock *sk = skb_steal_sock(skb); |
100 | 100 | ||
101 | if (unlikely(sk = skb_steal_sock(skb))) | 101 | if (sk) |
102 | return sk; | 102 | return sk; |
103 | else return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, | 103 | |
104 | &ipv6_hdr(skb)->saddr, sport, | 104 | return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, |
105 | &ipv6_hdr(skb)->daddr, ntohs(dport), | 105 | &ipv6_hdr(skb)->saddr, sport, |
106 | inet6_iif(skb)); | 106 | &ipv6_hdr(skb)->daddr, ntohs(dport), |
107 | inet6_iif(skb)); | ||
107 | } | 108 | } |
108 | 109 | ||
109 | extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, | 110 | extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, |
diff --git a/include/net/protocol.h b/include/net/protocol.h index 057f2d315567..929528c73fe8 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h | |||
@@ -52,6 +52,8 @@ struct net_protocol { | |||
52 | 52 | ||
53 | #if IS_ENABLED(CONFIG_IPV6) | 53 | #if IS_ENABLED(CONFIG_IPV6) |
54 | struct inet6_protocol { | 54 | struct inet6_protocol { |
55 | void (*early_demux)(struct sk_buff *skb); | ||
56 | |||
55 | int (*handler)(struct sk_buff *skb); | 57 | int (*handler)(struct sk_buff *skb); |
56 | 58 | ||
57 | void (*err_handler)(struct sk_buff *skb, | 59 | void (*err_handler)(struct sk_buff *skb, |
diff --git a/include/net/route.h b/include/net/route.h index c29ef2733f2d..8c52bc6f1c90 100644 --- a/include/net/route.h +++ b/include/net/route.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <net/inet_sock.h> | 30 | #include <net/inet_sock.h> |
31 | #include <linux/in_route.h> | 31 | #include <linux/in_route.h> |
32 | #include <linux/rtnetlink.h> | 32 | #include <linux/rtnetlink.h> |
33 | #include <linux/rcupdate.h> | ||
33 | #include <linux/route.h> | 34 | #include <linux/route.h> |
34 | #include <linux/ip.h> | 35 | #include <linux/ip.h> |
35 | #include <linux/cache.h> | 36 | #include <linux/cache.h> |
@@ -157,8 +158,22 @@ static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4 | |||
157 | return ip_route_output_key(net, fl4); | 158 | return ip_route_output_key(net, fl4); |
158 | } | 159 | } |
159 | 160 | ||
160 | extern int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src, | 161 | extern int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src, |
161 | u8 tos, struct net_device *devin); | 162 | u8 tos, struct net_device *devin); |
163 | |||
164 | static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src, | ||
165 | u8 tos, struct net_device *devin) | ||
166 | { | ||
167 | int err; | ||
168 | |||
169 | rcu_read_lock(); | ||
170 | err = ip_route_input_noref(skb, dst, src, tos, devin); | ||
171 | if (!err) | ||
172 | skb_dst_force(skb); | ||
173 | rcu_read_unlock(); | ||
174 | |||
175 | return err; | ||
176 | } | ||
162 | 177 | ||
163 | extern void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, | 178 | extern void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, |
164 | int oif, u32 mark, u8 protocol, int flow_flags); | 179 | int oif, u32 mark, u8 protocol, int flow_flags); |
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index a0124eb7dbea..77e87aff419a 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -827,7 +827,7 @@ static int arp_process(struct sk_buff *skb) | |||
827 | } | 827 | } |
828 | 828 | ||
829 | if (arp->ar_op == htons(ARPOP_REQUEST) && | 829 | if (arp->ar_op == htons(ARPOP_REQUEST) && |
830 | ip_route_input(skb, tip, sip, 0, dev) == 0) { | 830 | ip_route_input_noref(skb, tip, sip, 0, dev) == 0) { |
831 | 831 | ||
832 | rt = skb_rtable(skb); | 832 | rt = skb_rtable(skb); |
833 | addr_type = rt->rt_type; | 833 | addr_type = rt->rt_type; |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index e55171f184f9..da0cc2e6b250 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -172,9 +172,9 @@ static void free_fib_info_rcu(struct rcu_head *head) | |||
172 | if (nexthop_nh->nh_exceptions) | 172 | if (nexthop_nh->nh_exceptions) |
173 | free_nh_exceptions(nexthop_nh); | 173 | free_nh_exceptions(nexthop_nh); |
174 | if (nexthop_nh->nh_rth_output) | 174 | if (nexthop_nh->nh_rth_output) |
175 | dst_release(&nexthop_nh->nh_rth_output->dst); | 175 | dst_free(&nexthop_nh->nh_rth_output->dst); |
176 | if (nexthop_nh->nh_rth_input) | 176 | if (nexthop_nh->nh_rth_input) |
177 | dst_release(&nexthop_nh->nh_rth_input->dst); | 177 | dst_free(&nexthop_nh->nh_rth_input->dst); |
178 | } endfor_nexthops(fi); | 178 | } endfor_nexthops(fi); |
179 | 179 | ||
180 | release_net(fi->fib_net); | 180 | release_net(fi->fib_net); |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 7ad88e5e7110..8d07c973409c 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -258,8 +258,8 @@ static void ip_expire(unsigned long arg) | |||
258 | /* skb dst is stale, drop it, and perform route lookup again */ | 258 | /* skb dst is stale, drop it, and perform route lookup again */ |
259 | skb_dst_drop(head); | 259 | skb_dst_drop(head); |
260 | iph = ip_hdr(head); | 260 | iph = ip_hdr(head); |
261 | err = ip_route_input(head, iph->daddr, iph->saddr, | 261 | err = ip_route_input_noref(head, iph->daddr, iph->saddr, |
262 | iph->tos, head->dev); | 262 | iph->tos, head->dev); |
263 | if (err) | 263 | if (err) |
264 | goto out_rcu_unlock; | 264 | goto out_rcu_unlock; |
265 | 265 | ||
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 4ebc6feee250..981ff1eef28c 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -314,6 +314,7 @@ drop: | |||
314 | } | 314 | } |
315 | 315 | ||
316 | int sysctl_ip_early_demux __read_mostly = 1; | 316 | int sysctl_ip_early_demux __read_mostly = 1; |
317 | EXPORT_SYMBOL(sysctl_ip_early_demux); | ||
317 | 318 | ||
318 | static int ip_rcv_finish(struct sk_buff *skb) | 319 | static int ip_rcv_finish(struct sk_buff *skb) |
319 | { | 320 | { |
@@ -326,8 +327,11 @@ static int ip_rcv_finish(struct sk_buff *skb) | |||
326 | 327 | ||
327 | rcu_read_lock(); | 328 | rcu_read_lock(); |
328 | ipprot = rcu_dereference(inet_protos[protocol]); | 329 | ipprot = rcu_dereference(inet_protos[protocol]); |
329 | if (ipprot && ipprot->early_demux) | 330 | if (ipprot && ipprot->early_demux) { |
330 | ipprot->early_demux(skb); | 331 | ipprot->early_demux(skb); |
332 | /* must reload iph, skb->head might have changed */ | ||
333 | iph = ip_hdr(skb); | ||
334 | } | ||
331 | rcu_read_unlock(); | 335 | rcu_read_unlock(); |
332 | } | 336 | } |
333 | 337 | ||
@@ -336,8 +340,8 @@ static int ip_rcv_finish(struct sk_buff *skb) | |||
336 | * how the packet travels inside Linux networking. | 340 | * how the packet travels inside Linux networking. |
337 | */ | 341 | */ |
338 | if (!skb_dst(skb)) { | 342 | if (!skb_dst(skb)) { |
339 | int err = ip_route_input(skb, iph->daddr, iph->saddr, | 343 | int err = ip_route_input_noref(skb, iph->daddr, iph->saddr, |
340 | iph->tos, skb->dev); | 344 | iph->tos, skb->dev); |
341 | if (unlikely(err)) { | 345 | if (unlikely(err)) { |
342 | if (err == -EXDEV) | 346 | if (err == -EXDEV) |
343 | NET_INC_STATS_BH(dev_net(skb->dev), | 347 | NET_INC_STATS_BH(dev_net(skb->dev), |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 6bcb8fc71cbc..fc1a81ca79a7 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -444,7 +444,7 @@ static inline int ip_rt_proc_init(void) | |||
444 | } | 444 | } |
445 | #endif /* CONFIG_PROC_FS */ | 445 | #endif /* CONFIG_PROC_FS */ |
446 | 446 | ||
447 | static inline int rt_is_expired(struct rtable *rth) | 447 | static inline bool rt_is_expired(const struct rtable *rth) |
448 | { | 448 | { |
449 | return rth->rt_genid != rt_genid(dev_net(rth->dst.dev)); | 449 | return rth->rt_genid != rt_genid(dev_net(rth->dst.dev)); |
450 | } | 450 | } |
@@ -1199,10 +1199,9 @@ restart: | |||
1199 | fnhe->fnhe_stamp = jiffies; | 1199 | fnhe->fnhe_stamp = jiffies; |
1200 | } | 1200 | } |
1201 | 1201 | ||
1202 | static inline void rt_release_rcu(struct rcu_head *head) | 1202 | static inline void rt_free(struct rtable *rt) |
1203 | { | 1203 | { |
1204 | struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head); | 1204 | call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); |
1205 | dst_release(dst); | ||
1206 | } | 1205 | } |
1207 | 1206 | ||
1208 | static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) | 1207 | static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) |
@@ -1216,15 +1215,23 @@ static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) | |||
1216 | 1215 | ||
1217 | prev = cmpxchg(p, orig, rt); | 1216 | prev = cmpxchg(p, orig, rt); |
1218 | if (prev == orig) { | 1217 | if (prev == orig) { |
1219 | dst_clone(&rt->dst); | ||
1220 | if (orig) | 1218 | if (orig) |
1221 | call_rcu_bh(&orig->dst.rcu_head, rt_release_rcu); | 1219 | rt_free(orig); |
1220 | } else { | ||
1221 | /* Routes we intend to cache in the FIB nexthop have | ||
1222 | * the DST_NOCACHE bit clear. However, if we are | ||
1223 | * unsuccessful at storing this route into the cache | ||
1224 | * we really need to set it. | ||
1225 | */ | ||
1226 | rt->dst.flags |= DST_NOCACHE; | ||
1222 | } | 1227 | } |
1223 | } | 1228 | } |
1224 | 1229 | ||
1225 | static bool rt_cache_valid(struct rtable *rt) | 1230 | static bool rt_cache_valid(const struct rtable *rt) |
1226 | { | 1231 | { |
1227 | return (rt && rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK); | 1232 | return rt && |
1233 | rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK && | ||
1234 | !rt_is_expired(rt); | ||
1228 | } | 1235 | } |
1229 | 1236 | ||
1230 | static void rt_set_nexthop(struct rtable *rt, __be32 daddr, | 1237 | static void rt_set_nexthop(struct rtable *rt, __be32 daddr, |
@@ -1243,7 +1250,7 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, | |||
1243 | #ifdef CONFIG_IP_ROUTE_CLASSID | 1250 | #ifdef CONFIG_IP_ROUTE_CLASSID |
1244 | rt->dst.tclassid = nh->nh_tclassid; | 1251 | rt->dst.tclassid = nh->nh_tclassid; |
1245 | #endif | 1252 | #endif |
1246 | if (!(rt->dst.flags & DST_HOST)) | 1253 | if (!(rt->dst.flags & DST_NOCACHE)) |
1247 | rt_cache_route(nh, rt); | 1254 | rt_cache_route(nh, rt); |
1248 | } | 1255 | } |
1249 | 1256 | ||
@@ -1259,7 +1266,7 @@ static struct rtable *rt_dst_alloc(struct net_device *dev, | |||
1259 | bool nopolicy, bool noxfrm, bool will_cache) | 1266 | bool nopolicy, bool noxfrm, bool will_cache) |
1260 | { | 1267 | { |
1261 | return dst_alloc(&ipv4_dst_ops, dev, 1, DST_OBSOLETE_FORCE_CHK, | 1268 | return dst_alloc(&ipv4_dst_ops, dev, 1, DST_OBSOLETE_FORCE_CHK, |
1262 | (will_cache ? 0 : DST_HOST) | DST_NOCACHE | | 1269 | (will_cache ? 0 : (DST_HOST | DST_NOCACHE)) | |
1263 | (nopolicy ? DST_NOPOLICY : 0) | | 1270 | (nopolicy ? DST_NOPOLICY : 0) | |
1264 | (noxfrm ? DST_NOXFRM : 0)); | 1271 | (noxfrm ? DST_NOXFRM : 0)); |
1265 | } | 1272 | } |
@@ -1364,8 +1371,7 @@ static void ip_handle_martian_source(struct net_device *dev, | |||
1364 | static int __mkroute_input(struct sk_buff *skb, | 1371 | static int __mkroute_input(struct sk_buff *skb, |
1365 | const struct fib_result *res, | 1372 | const struct fib_result *res, |
1366 | struct in_device *in_dev, | 1373 | struct in_device *in_dev, |
1367 | __be32 daddr, __be32 saddr, u32 tos, | 1374 | __be32 daddr, __be32 saddr, u32 tos) |
1368 | struct rtable **result) | ||
1369 | { | 1375 | { |
1370 | struct rtable *rth; | 1376 | struct rtable *rth; |
1371 | int err; | 1377 | int err; |
@@ -1416,7 +1422,7 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1416 | if (!itag) { | 1422 | if (!itag) { |
1417 | rth = FIB_RES_NH(*res).nh_rth_input; | 1423 | rth = FIB_RES_NH(*res).nh_rth_input; |
1418 | if (rt_cache_valid(rth)) { | 1424 | if (rt_cache_valid(rth)) { |
1419 | dst_hold(&rth->dst); | 1425 | skb_dst_set_noref(skb, &rth->dst); |
1420 | goto out; | 1426 | goto out; |
1421 | } | 1427 | } |
1422 | do_cache = true; | 1428 | do_cache = true; |
@@ -1443,8 +1449,8 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1443 | rth->dst.output = ip_output; | 1449 | rth->dst.output = ip_output; |
1444 | 1450 | ||
1445 | rt_set_nexthop(rth, daddr, res, NULL, res->fi, res->type, itag); | 1451 | rt_set_nexthop(rth, daddr, res, NULL, res->fi, res->type, itag); |
1452 | skb_dst_set(skb, &rth->dst); | ||
1446 | out: | 1453 | out: |
1447 | *result = rth; | ||
1448 | err = 0; | 1454 | err = 0; |
1449 | cleanup: | 1455 | cleanup: |
1450 | return err; | 1456 | return err; |
@@ -1456,21 +1462,13 @@ static int ip_mkroute_input(struct sk_buff *skb, | |||
1456 | struct in_device *in_dev, | 1462 | struct in_device *in_dev, |
1457 | __be32 daddr, __be32 saddr, u32 tos) | 1463 | __be32 daddr, __be32 saddr, u32 tos) |
1458 | { | 1464 | { |
1459 | struct rtable *rth = NULL; | ||
1460 | int err; | ||
1461 | |||
1462 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 1465 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
1463 | if (res->fi && res->fi->fib_nhs > 1) | 1466 | if (res->fi && res->fi->fib_nhs > 1) |
1464 | fib_select_multipath(res); | 1467 | fib_select_multipath(res); |
1465 | #endif | 1468 | #endif |
1466 | 1469 | ||
1467 | /* create a routing cache entry */ | 1470 | /* create a routing cache entry */ |
1468 | err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, &rth); | 1471 | return __mkroute_input(skb, res, in_dev, daddr, saddr, tos); |
1469 | if (err) | ||
1470 | return err; | ||
1471 | |||
1472 | skb_dst_set(skb, &rth->dst); | ||
1473 | return 0; | ||
1474 | } | 1472 | } |
1475 | 1473 | ||
1476 | /* | 1474 | /* |
@@ -1586,8 +1584,9 @@ local_input: | |||
1586 | if (!itag) { | 1584 | if (!itag) { |
1587 | rth = FIB_RES_NH(res).nh_rth_input; | 1585 | rth = FIB_RES_NH(res).nh_rth_input; |
1588 | if (rt_cache_valid(rth)) { | 1586 | if (rt_cache_valid(rth)) { |
1589 | dst_hold(&rth->dst); | 1587 | skb_dst_set_noref(skb, &rth->dst); |
1590 | goto set_and_out; | 1588 | err = 0; |
1589 | goto out; | ||
1591 | } | 1590 | } |
1592 | do_cache = true; | 1591 | do_cache = true; |
1593 | } | 1592 | } |
@@ -1618,7 +1617,6 @@ local_input: | |||
1618 | } | 1617 | } |
1619 | if (do_cache) | 1618 | if (do_cache) |
1620 | rt_cache_route(&FIB_RES_NH(res), rth); | 1619 | rt_cache_route(&FIB_RES_NH(res), rth); |
1621 | set_and_out: | ||
1622 | skb_dst_set(skb, &rth->dst); | 1620 | skb_dst_set(skb, &rth->dst); |
1623 | err = 0; | 1621 | err = 0; |
1624 | goto out; | 1622 | goto out; |
@@ -1656,8 +1654,8 @@ martian_source_keep_err: | |||
1656 | goto out; | 1654 | goto out; |
1657 | } | 1655 | } |
1658 | 1656 | ||
1659 | int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, | 1657 | int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr, |
1660 | u8 tos, struct net_device *dev) | 1658 | u8 tos, struct net_device *dev) |
1661 | { | 1659 | { |
1662 | int res; | 1660 | int res; |
1663 | 1661 | ||
@@ -1700,7 +1698,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1700 | rcu_read_unlock(); | 1698 | rcu_read_unlock(); |
1701 | return res; | 1699 | return res; |
1702 | } | 1700 | } |
1703 | EXPORT_SYMBOL(ip_route_input); | 1701 | EXPORT_SYMBOL(ip_route_input_noref); |
1704 | 1702 | ||
1705 | /* called with rcu_read_lock() */ | 1703 | /* called with rcu_read_lock() */ |
1706 | static struct rtable *__mkroute_output(const struct fib_result *res, | 1704 | static struct rtable *__mkroute_output(const struct fib_result *res, |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3e30548ac32a..b6b07c93924c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1686,7 +1686,6 @@ void tcp_v4_early_demux(struct sk_buff *skb) | |||
1686 | struct net *net = dev_net(skb->dev); | 1686 | struct net *net = dev_net(skb->dev); |
1687 | const struct iphdr *iph; | 1687 | const struct iphdr *iph; |
1688 | const struct tcphdr *th; | 1688 | const struct tcphdr *th; |
1689 | struct net_device *dev; | ||
1690 | struct sock *sk; | 1689 | struct sock *sk; |
1691 | 1690 | ||
1692 | if (skb->pkt_type != PACKET_HOST) | 1691 | if (skb->pkt_type != PACKET_HOST) |
@@ -1701,14 +1700,10 @@ void tcp_v4_early_demux(struct sk_buff *skb) | |||
1701 | if (th->doff < sizeof(struct tcphdr) / 4) | 1700 | if (th->doff < sizeof(struct tcphdr) / 4) |
1702 | return; | 1701 | return; |
1703 | 1702 | ||
1704 | if (!pskb_may_pull(skb, ip_hdrlen(skb) + th->doff * 4)) | ||
1705 | return; | ||
1706 | |||
1707 | dev = skb->dev; | ||
1708 | sk = __inet_lookup_established(net, &tcp_hashinfo, | 1703 | sk = __inet_lookup_established(net, &tcp_hashinfo, |
1709 | iph->saddr, th->source, | 1704 | iph->saddr, th->source, |
1710 | iph->daddr, ntohs(th->dest), | 1705 | iph->daddr, ntohs(th->dest), |
1711 | dev->ifindex); | 1706 | skb->skb_iif); |
1712 | if (sk) { | 1707 | if (sk) { |
1713 | skb->sk = sk; | 1708 | skb->sk = sk; |
1714 | skb->destructor = sock_edemux; | 1709 | skb->destructor = sock_edemux; |
@@ -1718,7 +1713,7 @@ void tcp_v4_early_demux(struct sk_buff *skb) | |||
1718 | if (dst) | 1713 | if (dst) |
1719 | dst = dst_check(dst, 0); | 1714 | dst = dst_check(dst, 0); |
1720 | if (dst && | 1715 | if (dst && |
1721 | icsk->rx_dst_ifindex == dev->ifindex) | 1716 | icsk->rx_dst_ifindex == skb->skb_iif) |
1722 | skb_dst_set_noref(skb, dst); | 1717 | skb_dst_set_noref(skb, dst); |
1723 | } | 1718 | } |
1724 | } | 1719 | } |
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 58d23a572509..06814b6216dc 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c | |||
@@ -27,8 +27,8 @@ static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) | |||
27 | if (skb_dst(skb) == NULL) { | 27 | if (skb_dst(skb) == NULL) { |
28 | const struct iphdr *iph = ip_hdr(skb); | 28 | const struct iphdr *iph = ip_hdr(skb); |
29 | 29 | ||
30 | if (ip_route_input(skb, iph->daddr, iph->saddr, | 30 | if (ip_route_input_noref(skb, iph->daddr, iph->saddr, |
31 | iph->tos, skb->dev)) | 31 | iph->tos, skb->dev)) |
32 | goto drop; | 32 | goto drop; |
33 | } | 33 | } |
34 | return dst_input(skb); | 34 | return dst_input(skb); |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 5ab923e51af3..47975e363fcd 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -47,9 +47,18 @@ | |||
47 | 47 | ||
48 | 48 | ||
49 | 49 | ||
50 | inline int ip6_rcv_finish( struct sk_buff *skb) | 50 | int ip6_rcv_finish(struct sk_buff *skb) |
51 | { | 51 | { |
52 | if (skb_dst(skb) == NULL) | 52 | if (sysctl_ip_early_demux && !skb_dst(skb)) { |
53 | const struct inet6_protocol *ipprot; | ||
54 | |||
55 | rcu_read_lock(); | ||
56 | ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]); | ||
57 | if (ipprot && ipprot->early_demux) | ||
58 | ipprot->early_demux(skb); | ||
59 | rcu_read_unlock(); | ||
60 | } | ||
61 | if (!skb_dst(skb)) | ||
53 | ip6_route_input(skb); | 62 | ip6_route_input(skb); |
54 | 63 | ||
55 | return dst_input(skb); | 64 | return dst_input(skb); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f49476e2d884..221224e72507 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1674,6 +1674,43 @@ do_time_wait: | |||
1674 | goto discard_it; | 1674 | goto discard_it; |
1675 | } | 1675 | } |
1676 | 1676 | ||
1677 | static void tcp_v6_early_demux(struct sk_buff *skb) | ||
1678 | { | ||
1679 | const struct ipv6hdr *hdr; | ||
1680 | const struct tcphdr *th; | ||
1681 | struct sock *sk; | ||
1682 | |||
1683 | if (skb->pkt_type != PACKET_HOST) | ||
1684 | return; | ||
1685 | |||
1686 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr))) | ||
1687 | return; | ||
1688 | |||
1689 | hdr = ipv6_hdr(skb); | ||
1690 | th = tcp_hdr(skb); | ||
1691 | |||
1692 | if (th->doff < sizeof(struct tcphdr) / 4) | ||
1693 | return; | ||
1694 | |||
1695 | sk = __inet6_lookup_established(dev_net(skb->dev), &tcp_hashinfo, | ||
1696 | &hdr->saddr, th->source, | ||
1697 | &hdr->daddr, ntohs(th->dest), | ||
1698 | inet6_iif(skb)); | ||
1699 | if (sk) { | ||
1700 | skb->sk = sk; | ||
1701 | skb->destructor = sock_edemux; | ||
1702 | if (sk->sk_state != TCP_TIME_WAIT) { | ||
1703 | struct dst_entry *dst = sk->sk_rx_dst; | ||
1704 | struct inet_sock *icsk = inet_sk(sk); | ||
1705 | if (dst) | ||
1706 | dst = dst_check(dst, 0); | ||
1707 | if (dst && | ||
1708 | icsk->rx_dst_ifindex == inet6_iif(skb)) | ||
1709 | skb_dst_set_noref(skb, dst); | ||
1710 | } | ||
1711 | } | ||
1712 | } | ||
1713 | |||
1677 | static struct timewait_sock_ops tcp6_timewait_sock_ops = { | 1714 | static struct timewait_sock_ops tcp6_timewait_sock_ops = { |
1678 | .twsk_obj_size = sizeof(struct tcp6_timewait_sock), | 1715 | .twsk_obj_size = sizeof(struct tcp6_timewait_sock), |
1679 | .twsk_unique = tcp_twsk_unique, | 1716 | .twsk_unique = tcp_twsk_unique, |
@@ -1984,6 +2021,7 @@ struct proto tcpv6_prot = { | |||
1984 | }; | 2021 | }; |
1985 | 2022 | ||
1986 | static const struct inet6_protocol tcpv6_protocol = { | 2023 | static const struct inet6_protocol tcpv6_protocol = { |
2024 | .early_demux = tcp_v6_early_demux, | ||
1987 | .handler = tcp_v6_rcv, | 2025 | .handler = tcp_v6_rcv, |
1988 | .err_handler = tcp_v6_err, | 2026 | .err_handler = tcp_v6_err, |
1989 | .gso_send_check = tcp_v6_gso_send_check, | 2027 | .gso_send_check = tcp_v6_gso_send_check, |
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 788a12c1eb5d..2ab785064b7e 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c | |||
@@ -602,36 +602,31 @@ static int wanrouter_device_new_if(struct wan_device *wandev, | |||
602 | * successfully, add it to the interface list. | 602 | * successfully, add it to the interface list. |
603 | */ | 603 | */ |
604 | 604 | ||
605 | if (dev->name == NULL) { | 605 | #ifdef WANDEBUG |
606 | err = -EINVAL; | 606 | printk(KERN_INFO "%s: registering interface %s...\n", |
607 | } else { | 607 | wanrouter_modname, dev->name); |
608 | #endif | ||
608 | 609 | ||
609 | #ifdef WANDEBUG | 610 | err = register_netdev(dev); |
610 | printk(KERN_INFO "%s: registering interface %s...\n", | 611 | if (!err) { |
611 | wanrouter_modname, dev->name); | 612 | struct net_device *slave = NULL; |
612 | #endif | 613 | unsigned long smp_flags=0; |
613 | 614 | ||
614 | err = register_netdev(dev); | 615 | lock_adapter_irq(&wandev->lock, &smp_flags); |
615 | if (!err) { | 616 | |
616 | struct net_device *slave = NULL; | 617 | if (wandev->dev == NULL) { |
617 | unsigned long smp_flags=0; | 618 | wandev->dev = dev; |
618 | 619 | } else { | |
619 | lock_adapter_irq(&wandev->lock, &smp_flags); | 620 | for (slave=wandev->dev; |
620 | 621 | DEV_TO_SLAVE(slave); | |
621 | if (wandev->dev == NULL) { | 622 | slave = DEV_TO_SLAVE(slave)) |
622 | wandev->dev = dev; | 623 | DEV_TO_SLAVE(slave) = dev; |
623 | } else { | ||
624 | for (slave=wandev->dev; | ||
625 | DEV_TO_SLAVE(slave); | ||
626 | slave = DEV_TO_SLAVE(slave)) | ||
627 | DEV_TO_SLAVE(slave) = dev; | ||
628 | } | ||
629 | ++wandev->ndev; | ||
630 | |||
631 | unlock_adapter_irq(&wandev->lock, &smp_flags); | ||
632 | err = 0; /* done !!! */ | ||
633 | goto out; | ||
634 | } | 624 | } |
625 | ++wandev->ndev; | ||
626 | |||
627 | unlock_adapter_irq(&wandev->lock, &smp_flags); | ||
628 | err = 0; /* done !!! */ | ||
629 | goto out; | ||
635 | } | 630 | } |
636 | if (wandev->del_if) | 631 | if (wandev->del_if) |
637 | wandev->del_if(wandev, dev); | 632 | wandev->del_if(wandev, dev); |