diff --git a/[refs] b/[refs] index 1c0744a6c676..5962809bd71a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c5e90f562047ff9713183cf5e18f5e8997bc7373 +refs/heads/master: 8f1e1742233cd1c3444dfc6c945a2efb2814e157 diff --git a/trunk/Documentation/networking/phonet.txt b/trunk/Documentation/networking/phonet.txt index 24ad2adba6e5..2d9bc2b711fc 100644 --- a/trunk/Documentation/networking/phonet.txt +++ b/trunk/Documentation/networking/phonet.txt @@ -199,29 +199,33 @@ between itself and a remote pipe-end point (e.g. modem). The implementation adds socket options at SOL_PNPIPE level: - PNPIPE_PIPE_HANDLE - It accepts an integer argument for setting value of pipe handle. + PNPIPE_CREATE + It accepts an integer argument where-in + lower order 16 bits: pn_dev and pn_port pair for remote pep. + higher order 16 bits: 8 bit pipe-handle + + It sends a PNS_PEP_CONNECT_REQ on sequenced socket itself. On getting + PNS_PEP_CONNECT_RESP, it sends PNS_PEP_CONNECT_REQ to remote pep. On + getting response from remote pep, it selects the best possible Flow + control mechanism supported by remote-pep (modem) and then it sends + PNS_PEP_CREATED_IND to the sequenced socket and to the remote pep. + + It then updates the pipe state associated with the sequenced socket to + be PIPE_DISABLED. PNPIPE_ENABLE accepts one integer value (int). If set to zero, the pipe is disabled. If the value is non-zero, the pipe is enabled. If the pipe is not (yet) connected, ENOTCONN is error is returned. -The implementation also adds socket 'connect'. On calling the 'connect', pipe -will be created between the source socket and the destination, and the pipe -state will be set to PIPE_DISABLED. + PNPIPE_DESTROY + This will send out PNS_PEP_DISCONNECT_REQ on the sequenced socket and + the remote pep. + It will also update the pipe state associated with the sequenced socket + to PIPE_IDLE After a pipe has been created and enabled successfully, the Pipe data can be exchanged between the host-pep and remote-pep (modem). -User-space would typically follow below sequence with Pipe controller:- --socket --bind --setsockopt for PNPIPE_PIPE_HANDLE --connect --setsockopt for PNPIPE_ENCAP_IP --setsockopt for PNPIPE_ENABLE - - Authors ------- diff --git a/trunk/drivers/bluetooth/btmrvl_main.c b/trunk/drivers/bluetooth/btmrvl_main.c index 0d32ec82e9bf..548d1d9e4dda 100644 --- a/trunk/drivers/bluetooth/btmrvl_main.c +++ b/trunk/drivers/bluetooth/btmrvl_main.c @@ -117,8 +117,8 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) (event->data[2] == MODULE_ALREADY_UP)) ? "Bring-up succeed" : "Bring-up failed"); - if (event->length > 3) - priv->btmrvl_dev.dev_type = event->data[3]; + if (event->length > 3 && event->data[3]) + priv->btmrvl_dev.dev_type = HCI_AMP; else priv->btmrvl_dev.dev_type = HCI_BREDR; diff --git a/trunk/drivers/infiniband/hw/mlx4/Kconfig b/trunk/drivers/infiniband/hw/mlx4/Kconfig index bd995b2b50d8..4175a4bd0c78 100644 --- a/trunk/drivers/infiniband/hw/mlx4/Kconfig +++ b/trunk/drivers/infiniband/hw/mlx4/Kconfig @@ -1,6 +1,5 @@ config MLX4_INFINIBAND tristate "Mellanox ConnectX HCA support" - depends on NETDEVICES && NETDEV_10000 && PCI select MLX4_CORE ---help--- This driver provides low-level InfiniBand support for diff --git a/trunk/drivers/net/3c523.c b/trunk/drivers/net/3c523.c index de579d043169..ca00f0a11217 100644 --- a/trunk/drivers/net/3c523.c +++ b/trunk/drivers/net/3c523.c @@ -287,7 +287,7 @@ static int elmc_open(struct net_device *dev) elmc_id_attn586(); /* disable interrupts */ - ret = request_irq(dev->irq, elmc_interrupt, IRQF_SHARED, + ret = request_irq(dev->irq, elmc_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev); if (ret) { pr_err("%s: couldn't get irq %d\n", dev->name, dev->irq); diff --git a/trunk/drivers/net/3c527.c b/trunk/drivers/net/3c527.c index 0d6ca1e407d0..70705d1306b9 100644 --- a/trunk/drivers/net/3c527.c +++ b/trunk/drivers/net/3c527.c @@ -443,7 +443,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) * Grab the IRQ */ - err = request_irq(dev->irq, mc32_interrupt, IRQF_SHARED, DRV_NAME, dev); + err = request_irq(dev->irq, mc32_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM, DRV_NAME, dev); if (err) { release_region(dev->base_addr, MC32_IO_EXTENT); pr_err("%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq); diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index d24f54b8c19a..13d01f358f34 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -177,13 +177,6 @@ config NET_SB1000 source "drivers/net/arcnet/Kconfig" -config MII - tristate "Generic Media Independent Interface device support" - help - Most ethernet controllers have MII transceiver either as an external - or internal device. It is safe to say Y or M here even if your - ethernet card lacks MII. - source "drivers/net/phy/Kconfig" # @@ -219,6 +212,13 @@ menuconfig NET_ETHERNET if NET_ETHERNET +config MII + tristate "Generic Media Independent Interface device support" + help + Most ethernet controllers have MII transceiver either as an external + or internal device. It is safe to say Y or M here even if your + ethernet card lack MII. + config MACB tristate "Atmel MACB support" depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91SAM9G45 || ARCH_AT91CAP9 diff --git a/trunk/drivers/net/bnx2x/bnx2x.h b/trunk/drivers/net/bnx2x/bnx2x.h index 3bf236b160dd..c49b643e009b 100644 --- a/trunk/drivers/net/bnx2x/bnx2x.h +++ b/trunk/drivers/net/bnx2x/bnx2x.h @@ -20,8 +20,8 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ -#define DRV_MODULE_VERSION "1.60.00-3" -#define DRV_MODULE_RELDATE "2010/10/19" +#define DRV_MODULE_VERSION "1.60.00-1" +#define DRV_MODULE_RELDATE "2010/10/06" #define BNX2X_BC_VER 0x040200 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) @@ -1180,10 +1180,15 @@ struct bnx2x { TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY /* func init flags */ -#define FUNC_FLG_STATS 0x0001 -#define FUNC_FLG_TPA 0x0002 -#define FUNC_FLG_SPQ 0x0004 -#define FUNC_FLG_LEADING 0x0008 /* PF only */ +#define FUNC_FLG_RSS 0x0001 +#define FUNC_FLG_STATS 0x0002 +/* removed FUNC_FLG_UNMATCHED 0x0004 */ +#define FUNC_FLG_TPA 0x0008 +#define FUNC_FLG_SPQ 0x0010 +#define FUNC_FLG_LEADING 0x0020 /* PF only */ + +#define FUNC_CONFIG(flgs) ((flgs) & (FUNC_FLG_RSS | FUNC_FLG_TPA | \ + FUNC_FLG_LEADING)) struct rxq_pause_params { u16 bd_th_lo; diff --git a/trunk/drivers/net/bnx2x/bnx2x_cmn.c b/trunk/drivers/net/bnx2x/bnx2x_cmn.c index 1966ceeefcd4..97ef674dcc34 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_cmn.c +++ b/trunk/drivers/net/bnx2x/bnx2x_cmn.c @@ -507,11 +507,8 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) len = le16_to_cpu(cqe->fast_path_cqe.pkt_len); pad = cqe->fast_path_cqe.placement_offset; - /* - If CQE is marked both TPA_START and TPA_END it is - * a non-TPA CQE. - * - FP CQE will always have either TPA_START or/and - * TPA_STOP flags set. - */ + /* If CQE is marked both TPA_START and TPA_END + it is a non-TPA CQE */ if ((!fp->disable_tpa) && (TPA_TYPE(cqe_fp_flags) != (TPA_TYPE_START | TPA_TYPE_END))) { @@ -529,7 +526,9 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) bnx2x_set_skb_rxhash(bp, cqe, skb); goto next_rx; - } else { /* TPA_STOP */ + } + + if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_END) { DP(NETIF_MSG_RX_STATUS, "calling tpa_stop on queue %d\n", queue); @@ -831,7 +830,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) int i, j; bp->rx_buf_size = bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN + - IP_HEADER_ALIGNMENT_PADDING; + BNX2X_FW_IP_HDR_ALIGN_PAD; DP(NETIF_MSG_IFUP, "mtu %d rx_buf_size %d\n", bp->dev->mtu, bp->rx_buf_size); @@ -1289,6 +1288,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) if (rc) { BNX2X_ERR("HW init failed, aborting\n"); bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); goto load_error2; } @@ -1521,12 +1522,6 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) { u16 pmcsr; - /* If there is no power capability, silently succeed */ - if (!bp->pm_cap) { - DP(NETIF_MSG_HW, "No power capability. Breaking.\n"); - return 0; - } - pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr); switch (state) { diff --git a/trunk/drivers/net/bnx2x/bnx2x_cmn.h b/trunk/drivers/net/bnx2x/bnx2x_cmn.h index 5bfe0ab1d2d4..7f52cec9bb99 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_cmn.h +++ b/trunk/drivers/net/bnx2x/bnx2x_cmn.h @@ -1032,4 +1032,6 @@ static inline void storm_memset_cmng(struct bnx2x *bp, void bnx2x_acquire_phy_lock(struct bnx2x *bp); void bnx2x_release_phy_lock(struct bnx2x *bp); +#define BNX2X_FW_IP_HDR_ALIGN_PAD 2 /* FW places hdr with this padding */ + #endif /* BNX2X_CMN_H */ diff --git a/trunk/drivers/net/bnx2x/bnx2x_main.c b/trunk/drivers/net/bnx2x/bnx2x_main.c index f22e283cabef..ead524bca8f2 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_main.c +++ b/trunk/drivers/net/bnx2x/bnx2x_main.c @@ -1111,19 +1111,14 @@ static void bnx2x_hc_int_enable(struct bnx2x *bp) HC_CONFIG_0_REG_INT_LINE_EN_0 | HC_CONFIG_0_REG_ATTN_BIT_EN_0); - if (!CHIP_IS_E1(bp)) { - DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)\n", - val, port, addr); + DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)\n", + val, port, addr); - REG_WR(bp, addr, val); + REG_WR(bp, addr, val); - val &= ~HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0; - } + val &= ~HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0; } - if (CHIP_IS_E1(bp)) - REG_WR(bp, HC_REG_INT_MASK + port*4, 0x1FFFF); - DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x) mode %s\n", val, port, addr, (msix ? "MSI-X" : (msi ? "MSI" : "INTx"))); @@ -1217,26 +1212,10 @@ static void bnx2x_hc_int_disable(struct bnx2x *bp) u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0; u32 val = REG_RD(bp, addr); - /* - * in E1 we must use only PCI configuration space to disable - * MSI/MSIX capablility - * It's forbitten to disable IGU_PF_CONF_MSI_MSIX_EN in HC block - */ - if (CHIP_IS_E1(bp)) { - /* Since IGU_PF_CONF_MSI_MSIX_EN still always on - * Use mask register to prevent from HC sending interrupts - * after we exit the function - */ - REG_WR(bp, HC_REG_INT_MASK + port*4, 0); - - val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 | - HC_CONFIG_0_REG_INT_LINE_EN_0 | - HC_CONFIG_0_REG_ATTN_BIT_EN_0); - } else - val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 | - HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 | - HC_CONFIG_0_REG_INT_LINE_EN_0 | - HC_CONFIG_0_REG_ATTN_BIT_EN_0); + val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 | + HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 | + HC_CONFIG_0_REG_INT_LINE_EN_0 | + HC_CONFIG_0_REG_ATTN_BIT_EN_0); DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)\n", val, port, addr); @@ -2305,31 +2284,35 @@ void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters) void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p) { - struct tstorm_eth_function_common_config tcfg = {0}; - u16 rss_flgs; + if (FUNC_CONFIG(p->func_flgs)) { + struct tstorm_eth_function_common_config tcfg = {0}; + + /* tpa */ + if (p->func_flgs & FUNC_FLG_TPA) + tcfg.config_flags |= + TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA; - /* tpa */ - if (p->func_flgs & FUNC_FLG_TPA) - tcfg.config_flags |= - TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA; + /* set rss flags */ + if (p->func_flgs & FUNC_FLG_RSS) { + u16 rss_flgs = (p->rss->mode << + TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT); - /* set rss flags */ - rss_flgs = (p->rss->mode << - TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT); + if (p->rss->cap & RSS_IPV4_CAP) + rss_flgs |= RSS_IPV4_CAP_MASK; + if (p->rss->cap & RSS_IPV4_TCP_CAP) + rss_flgs |= RSS_IPV4_TCP_CAP_MASK; + if (p->rss->cap & RSS_IPV6_CAP) + rss_flgs |= RSS_IPV6_CAP_MASK; + if (p->rss->cap & RSS_IPV6_TCP_CAP) + rss_flgs |= RSS_IPV6_TCP_CAP_MASK; - if (p->rss->cap & RSS_IPV4_CAP) - rss_flgs |= RSS_IPV4_CAP_MASK; - if (p->rss->cap & RSS_IPV4_TCP_CAP) - rss_flgs |= RSS_IPV4_TCP_CAP_MASK; - if (p->rss->cap & RSS_IPV6_CAP) - rss_flgs |= RSS_IPV6_CAP_MASK; - if (p->rss->cap & RSS_IPV6_TCP_CAP) - rss_flgs |= RSS_IPV6_TCP_CAP_MASK; + tcfg.config_flags |= rss_flgs; + tcfg.rss_result_mask = p->rss->result_mask; - tcfg.config_flags |= rss_flgs; - tcfg.rss_result_mask = p->rss->result_mask; + } - storm_memset_func_cfg(bp, &tcfg, p->func_id); + storm_memset_func_cfg(bp, &tcfg, p->func_id); + } /* Enable the function in the FW */ storm_memset_vf_to_pf(bp, p->func_id, p->pf_id); @@ -2496,17 +2479,23 @@ void bnx2x_pf_init(struct bnx2x *bp) else flags |= FUNC_FLG_TPA; - /* function setup */ - /** * Although RSS is meaningless when there is a single HW queue we * still need it enabled in order to have HW Rx hash generated. + * + * if (is_eth_multi(bp)) + * flags |= FUNC_FLG_RSS; */ - rss.cap = (RSS_IPV4_CAP | RSS_IPV4_TCP_CAP | - RSS_IPV6_CAP | RSS_IPV6_TCP_CAP); - rss.mode = bp->multi_mode; - rss.result_mask = MULTI_MASK; - func_init.rss = &rss; + flags |= FUNC_FLG_RSS; + + /* function setup */ + if (flags & FUNC_FLG_RSS) { + rss.cap = (RSS_IPV4_CAP | RSS_IPV4_TCP_CAP | + RSS_IPV6_CAP | RSS_IPV6_TCP_CAP); + rss.mode = bp->multi_mode; + rss.result_mask = MULTI_MASK; + func_init.rss = &rss; + } func_init.func_flgs = flags; func_init.pf_id = BP_FUNC(bp); @@ -5457,8 +5446,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) struct bnx2x_ilt *ilt = BP_ILT(bp); u16 cdu_ilt_start; u32 addr, val; - u32 main_mem_base, main_mem_size, main_mem_prty_clr; - int i, main_mem_width; + int i; DP(BNX2X_MSG_MCP, "starting func init func %d\n", func); @@ -5707,31 +5695,6 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) bnx2x_init_block(bp, MCP_BLOCK, FUNC0_STAGE + func); bnx2x_init_block(bp, DMAE_BLOCK, FUNC0_STAGE + func); - if (CHIP_IS_E1x(bp)) { - main_mem_size = HC_REG_MAIN_MEMORY_SIZE / 2; /*dwords*/ - main_mem_base = HC_REG_MAIN_MEMORY + - BP_PORT(bp) * (main_mem_size * 4); - main_mem_prty_clr = HC_REG_HC_PRTY_STS_CLR; - main_mem_width = 8; - - val = REG_RD(bp, main_mem_prty_clr); - if (val) - DP(BNX2X_MSG_MCP, "Hmmm... Parity errors in HC " - "block during " - "function init (0x%x)!\n", val); - - /* Clear "false" parity errors in MSI-X table */ - for (i = main_mem_base; - i < main_mem_base + main_mem_size * 4; - i += main_mem_width) { - bnx2x_read_dmae(bp, i, main_mem_width / 4); - bnx2x_write_dmae(bp, bnx2x_sp_mapping(bp, wb_data), - i, main_mem_width / 4); - } - /* Clear HC parity attention */ - REG_RD(bp, main_mem_prty_clr); - } - bnx2x_phy_probe(&bp->link_params); return 0; diff --git a/trunk/drivers/net/bnx2x/bnx2x_reg.h b/trunk/drivers/net/bnx2x/bnx2x_reg.h index 1cefe489a955..18a86284ebcc 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_reg.h +++ b/trunk/drivers/net/bnx2x/bnx2x_reg.h @@ -800,13 +800,9 @@ #define HC_REG_HC_PRTY_MASK 0x1080a0 /* [R 3] Parity register #0 read */ #define HC_REG_HC_PRTY_STS 0x108094 -/* [RC 3] Parity register #0 read clear */ -#define HC_REG_HC_PRTY_STS_CLR 0x108098 -#define HC_REG_INT_MASK 0x108108 +#define HC_REG_INT_MASK 0x108108 #define HC_REG_LEADING_EDGE_0 0x108040 #define HC_REG_LEADING_EDGE_1 0x108048 -#define HC_REG_MAIN_MEMORY 0x108800 -#define HC_REG_MAIN_MEMORY_SIZE 152 #define HC_REG_P0_PROD_CONS 0x108200 #define HC_REG_P1_PROD_CONS 0x108400 #define HC_REG_PBA_COMMAND 0x108140 diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index 6b9a7bd8ec14..7703d35de65d 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -76,7 +76,6 @@ #include #include #include -#include #include #include #include @@ -170,10 +169,6 @@ MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on link /*----------------------------- Global variables ----------------------------*/ -#ifdef CONFIG_NET_POLL_CONTROLLER -cpumask_var_t netpoll_block_tx; -#endif - static const char * const version = DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"; @@ -184,6 +179,9 @@ static int arp_ip_count; static int bond_mode = BOND_MODE_ROUNDROBIN; static int xmit_hashtype = BOND_XMIT_POLICY_LAYER2; static int lacp_fast; +#ifdef CONFIG_NET_POLL_CONTROLLER +static int disable_netpoll = 1; +#endif const struct bond_parm_tbl bond_lacp_tbl[] = { { "slow", AD_LACP_SLOW}, @@ -312,7 +310,6 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id) pr_debug("bond: %s, vlan id %d\n", bond->dev->name, vlan_id); - block_netpoll_tx(); write_lock_bh(&bond->lock); list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { @@ -347,7 +344,6 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id) out: write_unlock_bh(&bond->lock); - unblock_netpoll_tx(); return res; } @@ -453,9 +449,11 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, if (unlikely(bond->dev->priv_flags & IFF_IN_NETPOLL)) { struct netpoll *np = bond->dev->npinfo->netpoll; slave_dev->npinfo = bond->dev->npinfo; + np->real_dev = np->dev = skb->dev; slave_dev->priv_flags |= IFF_IN_NETPOLL; - netpoll_send_skb_on_dev(np, skb, slave_dev); + netpoll_send_skb(np, skb); slave_dev->priv_flags &= ~IFF_IN_NETPOLL; + np->dev = bond->dev; } else #endif dev_queue_xmit(skb); @@ -1334,14 +1332,9 @@ static bool slaves_support_netpoll(struct net_device *bond_dev) static void bond_poll_controller(struct net_device *bond_dev) { - struct bonding *bond = netdev_priv(bond_dev); - struct slave *slave; - int i; - - bond_for_each_slave(bond, slave, i) { - if (slave->dev && IS_UP(slave->dev)) - netpoll_poll_dev(slave->dev); - } + struct net_device *dev = bond_dev->npinfo->netpoll->real_dev; + if (dev != bond_dev) + netpoll_poll_dev(dev); } static void bond_netpoll_cleanup(struct net_device *bond_dev) @@ -1808,15 +1801,23 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_set_carrier(bond); #ifdef CONFIG_NET_POLL_CONTROLLER - if (slaves_support_netpoll(bond_dev)) { - bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; - if (bond_dev->npinfo) - slave_dev->npinfo = bond_dev->npinfo; - } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) { + /* + * Netpoll and bonding is broken, make sure it is not initialized + * until it is fixed. + */ + if (disable_netpoll) { bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; - pr_info("New slave device %s does not support netpoll\n", - slave_dev->name); - pr_info("Disabling netpoll support for %s\n", bond_dev->name); + } else { + if (slaves_support_netpoll(bond_dev)) { + bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; + if (bond_dev->npinfo) + slave_dev->npinfo = bond_dev->npinfo; + } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) { + bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; + pr_info("New slave device %s does not support netpoll\n", + slave_dev->name); + pr_info("Disabling netpoll support for %s\n", bond_dev->name); + } } #endif read_unlock(&bond->lock); @@ -1888,7 +1889,6 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) return -EINVAL; } - block_netpoll_tx(); netdev_bonding_change(bond_dev, NETDEV_BONDING_DESLAVE); write_lock_bh(&bond->lock); @@ -1898,7 +1898,6 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) pr_info("%s: %s not enslaved\n", bond_dev->name, slave_dev->name); write_unlock_bh(&bond->lock); - unblock_netpoll_tx(); return -EINVAL; } @@ -1992,7 +1991,6 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) } write_unlock_bh(&bond->lock); - unblock_netpoll_tx(); /* must do this from outside any spinlocks */ bond_destroy_slave_symlinks(bond_dev, slave_dev); @@ -2023,8 +2021,10 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) #ifdef CONFIG_NET_POLL_CONTROLLER read_lock_bh(&bond->lock); - if (slaves_support_netpoll(bond_dev)) - bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; + /* Make sure netpoll over stays disabled until fixed. */ + if (!disable_netpoll) + if (slaves_support_netpoll(bond_dev)) + bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; read_unlock_bh(&bond->lock); if (slave_dev->netdev_ops->ndo_netpoll_cleanup) slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev); @@ -2180,6 +2180,7 @@ static int bond_release_all(struct net_device *bond_dev) out: write_unlock_bh(&bond->lock); + return 0; } @@ -2228,11 +2229,9 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi (old_active) && (new_active->link == BOND_LINK_UP) && IS_UP(new_active->dev)) { - block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_change_active_slave(bond, new_active); write_unlock_bh(&bond->curr_slave_lock); - unblock_netpoll_tx(); } else res = -EINVAL; @@ -2464,11 +2463,9 @@ static void bond_miimon_commit(struct bonding *bond) do_failover: ASSERT_RTNL(); - block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); - unblock_netpoll_tx(); } bond_set_carrier(bond); @@ -2911,13 +2908,11 @@ void bond_loadbalance_arp_mon(struct work_struct *work) } if (do_failover) { - block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); - unblock_netpoll_tx(); } re_arm: @@ -3076,11 +3071,9 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) do_failover: ASSERT_RTNL(); - block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); - unblock_netpoll_tx(); } bond_set_carrier(bond); @@ -4568,13 +4561,6 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct bonding *bond = netdev_priv(dev); - /* - * If we risk deadlock from transmitting this in the - * netpoll path, tell netpoll to queue the frame for later tx - */ - if (is_netpoll_tx_blocked(dev)) - return NETDEV_TX_BUSY; - if (TX_QUEUE_OVERRIDE(bond->params.mode)) { if (!bond_slave_override(bond, skb)) return NETDEV_TX_OK; @@ -5297,13 +5283,6 @@ static int __init bonding_init(void) if (res) goto out; -#ifdef CONFIG_NET_POLL_CONTROLLER - if (!alloc_cpumask_var(&netpoll_block_tx, GFP_KERNEL)) { - res = -ENOMEM; - goto out; - } -#endif - res = register_pernet_subsys(&bond_net_ops); if (res) goto out; @@ -5322,7 +5301,6 @@ static int __init bonding_init(void) if (res) goto err; - register_netdevice_notifier(&bond_netdev_notifier); register_inetaddr_notifier(&bond_inetaddr_notifier); bond_register_ipv6_notifier(); @@ -5332,9 +5310,6 @@ static int __init bonding_init(void) rtnl_link_unregister(&bond_link_ops); err_link: unregister_pernet_subsys(&bond_net_ops); -#ifdef CONFIG_NET_POLL_CONTROLLER - free_cpumask_var(netpoll_block_tx); -#endif goto out; } @@ -5349,10 +5324,6 @@ static void __exit bonding_exit(void) rtnl_link_unregister(&bond_link_ops); unregister_pernet_subsys(&bond_net_ops); - -#ifdef CONFIG_NET_POLL_CONTROLLER - free_cpumask_var(netpoll_block_tx); -#endif } module_init(bonding_init); diff --git a/trunk/drivers/net/bonding/bond_sysfs.c b/trunk/drivers/net/bonding/bond_sysfs.c index 8fd0174c5380..01b4c3f5d9e7 100644 --- a/trunk/drivers/net/bonding/bond_sysfs.c +++ b/trunk/drivers/net/bonding/bond_sysfs.c @@ -1066,7 +1066,6 @@ static ssize_t bonding_store_primary(struct device *d, if (!rtnl_trylock()) return restart_syscall(); - block_netpoll_tx(); read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); @@ -1102,7 +1101,6 @@ static ssize_t bonding_store_primary(struct device *d, out: write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); - unblock_netpoll_tx(); rtnl_unlock(); return count; @@ -1148,13 +1146,11 @@ static ssize_t bonding_store_primary_reselect(struct device *d, bond->dev->name, pri_reselect_tbl[new_value].modename, new_value); - block_netpoll_tx(); read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); - unblock_netpoll_tx(); out: rtnl_unlock(); return ret; @@ -1236,8 +1232,6 @@ static ssize_t bonding_store_active_slave(struct device *d, if (!rtnl_trylock()) return restart_syscall(); - - block_netpoll_tx(); read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); @@ -1294,8 +1288,6 @@ static ssize_t bonding_store_active_slave(struct device *d, out: write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); - unblock_netpoll_tx(); - rtnl_unlock(); return count; diff --git a/trunk/drivers/net/bonding/bonding.h b/trunk/drivers/net/bonding/bonding.h index 2c12a5f812f4..c15f21347486 100644 --- a/trunk/drivers/net/bonding/bonding.h +++ b/trunk/drivers/net/bonding/bonding.h @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "bond_3ad.h" #include "bond_alb.h" @@ -118,35 +117,6 @@ bond_for_each_slave_from(bond, pos, cnt, (bond)->first_slave) -#ifdef CONFIG_NET_POLL_CONTROLLER -extern cpumask_var_t netpoll_block_tx; - -static inline void block_netpoll_tx(void) -{ - preempt_disable(); - BUG_ON(cpumask_test_and_set_cpu(smp_processor_id(), - netpoll_block_tx)); -} - -static inline void unblock_netpoll_tx(void) -{ - BUG_ON(!cpumask_test_and_clear_cpu(smp_processor_id(), - netpoll_block_tx)); - preempt_enable(); -} - -static inline int is_netpoll_tx_blocked(struct net_device *dev) -{ - if (unlikely(dev->priv_flags & IFF_IN_NETPOLL)) - return cpumask_test_cpu(smp_processor_id(), netpoll_block_tx); - return 0; -} -#else -#define block_netpoll_tx() -#define unblock_netpoll_tx() -#define is_netpoll_tx_blocked(dev) (0) -#endif - struct bond_params { int mode; int xmit_policy; diff --git a/trunk/drivers/net/can/mcp251x.c b/trunk/drivers/net/can/mcp251x.c index c664be261e98..b11a0cb5ed81 100644 --- a/trunk/drivers/net/can/mcp251x.c +++ b/trunk/drivers/net/can/mcp251x.c @@ -38,14 +38,14 @@ * static struct mcp251x_platform_data mcp251x_info = { * .oscillator_frequency = 8000000, * .board_specific_setup = &mcp251x_setup, + * .model = CAN_MCP251X_MCP2510, * .power_enable = mcp251x_power_enable, * .transceiver_enable = NULL, * }; * * static struct spi_board_info spi_board_info[] = { * { - * .modalias = "mcp2510", - * // or "mcp2515" depending on your controller + * .modalias = "mcp251x", * .platform_data = &mcp251x_info, * .irq = IRQ_EINT13, * .max_speed_hz = 2*1000*1000, @@ -125,8 +125,6 @@ # define CANINTF_TX0IF 0x04 # define CANINTF_RX1IF 0x02 # define CANINTF_RX0IF 0x01 -# define CANINTF_ERR_TX \ - (CANINTF_ERRIF | CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF) #define EFLG 0x2d # define EFLG_EWARN 0x01 # define EFLG_RXWAR 0x02 @@ -224,16 +222,10 @@ static struct can_bittiming_const mcp251x_bittiming_const = { .brp_inc = 1, }; -enum mcp251x_model { - CAN_MCP251X_MCP2510 = 0x2510, - CAN_MCP251X_MCP2515 = 0x2515, -}; - struct mcp251x_priv { struct can_priv can; struct net_device *net; struct spi_device *spi; - enum mcp251x_model model; struct mutex mcp_lock; /* SPI device lock */ @@ -258,16 +250,6 @@ struct mcp251x_priv { int restart_tx; }; -#define MCP251X_IS(_model) \ -static inline int mcp251x_is_##_model(struct spi_device *spi) \ -{ \ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); \ - return priv->model == CAN_MCP251X_MCP##_model; \ -} - -MCP251X_IS(2510); -MCP251X_IS(2515); - static void mcp251x_clean(struct net_device *net) { struct mcp251x_priv *priv = netdev_priv(net); @@ -337,20 +319,6 @@ static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg) return val; } -static void mcp251x_read_2regs(struct spi_device *spi, uint8_t reg, - uint8_t *v1, uint8_t *v2) -{ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - - priv->spi_tx_buf[0] = INSTRUCTION_READ; - priv->spi_tx_buf[1] = reg; - - mcp251x_spi_trans(spi, 4); - - *v1 = priv->spi_rx_buf[2]; - *v2 = priv->spi_rx_buf[3]; -} - static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val) { struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); @@ -378,9 +346,10 @@ static void mcp251x_write_bits(struct spi_device *spi, u8 reg, static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, int len, int tx_buf_idx) { + struct mcp251x_platform_data *pdata = spi->dev.platform_data; struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - if (mcp251x_is_2510(spi)) { + if (pdata->model == CAN_MCP251X_MCP2510) { int i; for (i = 1; i < TXBDAT_OFF + len; i++) @@ -423,8 +392,9 @@ static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, int buf_idx) { struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); + struct mcp251x_platform_data *pdata = spi->dev.platform_data; - if (mcp251x_is_2510(spi)) { + if (pdata->model == CAN_MCP251X_MCP2510) { int i, len; for (i = 1; i < RXBDAT_OFF; i++) @@ -481,7 +451,7 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx) priv->net->stats.rx_packets++; priv->net->stats.rx_bytes += frame->can_dlc; - netif_rx_ni(skb); + netif_rx(skb); } static void mcp251x_hw_sleep(struct spi_device *spi) @@ -706,7 +676,7 @@ static void mcp251x_error_skb(struct net_device *net, int can_id, int data1) if (skb) { frame->can_id = can_id; frame->data[1] = data1; - netif_rx_ni(skb); + netif_rx(skb); } else { dev_err(&net->dev, "cannot allocate error skb\n"); @@ -784,39 +754,24 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) mutex_lock(&priv->mcp_lock); while (!priv->force_quit) { enum can_state new_state; - u8 intf, eflag; - u8 clear_intf = 0; + u8 intf = mcp251x_read_reg(spi, CANINTF); + u8 eflag; int can_id = 0, data1 = 0; - mcp251x_read_2regs(spi, CANINTF, &intf, &eflag); - - /* receive buffer 0 */ if (intf & CANINTF_RX0IF) { mcp251x_hw_rx(spi, 0); - /* - * Free one buffer ASAP - * (The MCP2515 does this automatically.) - */ - if (mcp251x_is_2510(spi)) - mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00); + /* Free one buffer ASAP */ + mcp251x_write_bits(spi, CANINTF, intf & CANINTF_RX0IF, + 0x00); } - /* receive buffer 1 */ - if (intf & CANINTF_RX1IF) { + if (intf & CANINTF_RX1IF) mcp251x_hw_rx(spi, 1); - /* the MCP2515 does this automatically */ - if (mcp251x_is_2510(spi)) - clear_intf |= CANINTF_RX1IF; - } - /* any error or tx interrupt we need to clear? */ - if (intf & CANINTF_ERR_TX) - clear_intf |= intf & CANINTF_ERR_TX; - if (clear_intf) - mcp251x_write_bits(spi, CANINTF, clear_intf, 0x00); + mcp251x_write_bits(spi, CANINTF, intf, 0x00); - if (eflag) - mcp251x_write_bits(spi, EFLG, eflag, 0x00); + eflag = mcp251x_read_reg(spi, EFLG); + mcp251x_write_reg(spi, EFLG, 0x00); /* Update can state */ if (eflag & EFLG_TXBO) { @@ -861,14 +816,10 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) if (intf & CANINTF_ERRIF) { /* Handle overflow counters */ if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) { - if (eflag & EFLG_RX0OVR) { + if (eflag & EFLG_RX0OVR) net->stats.rx_over_errors++; - net->stats.rx_errors++; - } - if (eflag & EFLG_RX1OVR) { + if (eflag & EFLG_RX1OVR) net->stats.rx_over_errors++; - net->stats.rx_errors++; - } can_id |= CAN_ERR_CRTL; data1 |= CAN_ERR_CRTL_RX_OVERFLOW; } @@ -970,12 +921,16 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi) struct net_device *net; struct mcp251x_priv *priv; struct mcp251x_platform_data *pdata = spi->dev.platform_data; + int model = spi_get_device_id(spi)->driver_data; int ret = -ENODEV; if (!pdata) /* Platform data is required for osc freq */ goto error_out; + if (model) + pdata->model = model; + /* Allocate can/net device */ net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX); if (!net) { @@ -992,7 +947,6 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi) priv->can.clock.freq = pdata->oscillator_frequency / 2; priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; - priv->model = spi_get_device_id(spi)->driver_data; priv->net = net; dev_set_drvdata(&spi->dev, priv); @@ -1166,7 +1120,8 @@ static int mcp251x_can_resume(struct spi_device *spi) #define mcp251x_can_resume NULL #endif -static const struct spi_device_id mcp251x_id_table[] = { +static struct spi_device_id mcp251x_id_table[] = { + { "mcp251x", 0 /* Use pdata.model */ }, { "mcp2510", CAN_MCP251X_MCP2510 }, { "mcp2515", CAN_MCP251X_MCP2515 }, { }, diff --git a/trunk/drivers/net/cnic.c b/trunk/drivers/net/cnic.c index 92bac19ad60a..27449bf775e3 100644 --- a/trunk/drivers/net/cnic.c +++ b/trunk/drivers/net/cnic.c @@ -60,7 +60,6 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(CNIC_MODULE_VERSION); static LIST_HEAD(cnic_dev_list); -static LIST_HEAD(cnic_udev_list); static DEFINE_RWLOCK(cnic_dev_lock); static DEFINE_MUTEX(cnic_lock); @@ -82,34 +81,29 @@ static struct cnic_ops cnic_bnx2x_ops = { .cnic_ctl = cnic_ctl, }; -static struct workqueue_struct *cnic_wq; - static void cnic_shutdown_rings(struct cnic_dev *); static void cnic_init_rings(struct cnic_dev *); static int cnic_cm_set_pg(struct cnic_sock *); static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode) { - struct cnic_uio_dev *udev = uinfo->priv; - struct cnic_dev *dev; + struct cnic_dev *dev = uinfo->priv; + struct cnic_local *cp = dev->cnic_priv; if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (udev->uio_dev != -1) + if (cp->uio_dev != -1) return -EBUSY; rtnl_lock(); - dev = udev->dev; - - if (!dev || !test_bit(CNIC_F_CNIC_UP, &dev->flags)) { + if (!test_bit(CNIC_F_CNIC_UP, &dev->flags)) { rtnl_unlock(); return -ENODEV; } - udev->uio_dev = iminor(inode); + cp->uio_dev = iminor(inode); - cnic_shutdown_rings(dev); cnic_init_rings(dev); rtnl_unlock(); @@ -118,9 +112,12 @@ static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode) static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode) { - struct cnic_uio_dev *udev = uinfo->priv; + struct cnic_dev *dev = uinfo->priv; + struct cnic_local *cp = dev->cnic_priv; - udev->uio_dev = -1; + cnic_shutdown_rings(dev); + + cp->uio_dev = -1; return 0; } @@ -277,9 +274,8 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type, u16 len = 0; u32 msg_type = ISCSI_KEVENT_IF_DOWN; struct cnic_ulp_ops *ulp_ops; - struct cnic_uio_dev *udev = cp->udev; - if (!udev || udev->uio_dev == -1) + if (cp->uio_dev == -1) return -ENODEV; if (csk) { @@ -410,7 +406,8 @@ static void cnic_uio_stop(void) list_for_each_entry(dev, &cnic_dev_list, list) { struct cnic_local *cp = dev->cnic_priv; - cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); + if (cp->cnic_uinfo) + cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); } read_unlock(&cnic_dev_lock); } @@ -771,45 +768,31 @@ static void cnic_free_context(struct cnic_dev *dev) } } -static void __cnic_free_uio(struct cnic_uio_dev *udev) +static void cnic_free_resc(struct cnic_dev *dev) { - uio_unregister_device(&udev->cnic_uinfo); + struct cnic_local *cp = dev->cnic_priv; + int i = 0; - if (udev->l2_buf) { - dma_free_coherent(&udev->pdev->dev, udev->l2_buf_size, - udev->l2_buf, udev->l2_buf_map); - udev->l2_buf = NULL; + if (cp->cnic_uinfo) { + while (cp->uio_dev != -1 && i < 15) { + msleep(100); + i++; + } + uio_unregister_device(cp->cnic_uinfo); + kfree(cp->cnic_uinfo); + cp->cnic_uinfo = NULL; } - if (udev->l2_ring) { - dma_free_coherent(&udev->pdev->dev, udev->l2_ring_size, - udev->l2_ring, udev->l2_ring_map); - udev->l2_ring = NULL; + if (cp->l2_buf) { + dma_free_coherent(&dev->pcidev->dev, cp->l2_buf_size, + cp->l2_buf, cp->l2_buf_map); + cp->l2_buf = NULL; } - pci_dev_put(udev->pdev); - kfree(udev); -} - -static void cnic_free_uio(struct cnic_uio_dev *udev) -{ - if (!udev) - return; - - write_lock(&cnic_dev_lock); - list_del_init(&udev->list); - write_unlock(&cnic_dev_lock); - __cnic_free_uio(udev); -} - -static void cnic_free_resc(struct cnic_dev *dev) -{ - struct cnic_local *cp = dev->cnic_priv; - struct cnic_uio_dev *udev = cp->udev; - - if (udev) { - udev->dev = NULL; - cp->udev = NULL; + if (cp->l2_ring) { + dma_free_coherent(&dev->pcidev->dev, cp->l2_ring_size, + cp->l2_ring, cp->l2_ring_map); + cp->l2_ring = NULL; } cnic_free_context(dev); @@ -911,68 +894,37 @@ static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info) return 0; } -static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages) +static int cnic_alloc_l2_rings(struct cnic_dev *dev, int pages) { struct cnic_local *cp = dev->cnic_priv; - struct cnic_uio_dev *udev; - - read_lock(&cnic_dev_lock); - list_for_each_entry(udev, &cnic_udev_list, list) { - if (udev->pdev == dev->pcidev) { - udev->dev = dev; - cp->udev = udev; - read_unlock(&cnic_dev_lock); - return 0; - } - } - read_unlock(&cnic_dev_lock); - - udev = kzalloc(sizeof(struct cnic_uio_dev), GFP_ATOMIC); - if (!udev) - return -ENOMEM; - - udev->uio_dev = -1; - udev->dev = dev; - udev->pdev = dev->pcidev; - udev->l2_ring_size = pages * BCM_PAGE_SIZE; - udev->l2_ring = dma_alloc_coherent(&udev->pdev->dev, udev->l2_ring_size, - &udev->l2_ring_map, - GFP_KERNEL | __GFP_COMP); - if (!udev->l2_ring) + cp->l2_ring_size = pages * BCM_PAGE_SIZE; + cp->l2_ring = dma_alloc_coherent(&dev->pcidev->dev, cp->l2_ring_size, + &cp->l2_ring_map, + GFP_KERNEL | __GFP_COMP); + if (!cp->l2_ring) return -ENOMEM; - udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size; - udev->l2_buf_size = PAGE_ALIGN(udev->l2_buf_size); - udev->l2_buf = dma_alloc_coherent(&udev->pdev->dev, udev->l2_buf_size, - &udev->l2_buf_map, - GFP_KERNEL | __GFP_COMP); - if (!udev->l2_buf) + cp->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size; + cp->l2_buf_size = PAGE_ALIGN(cp->l2_buf_size); + cp->l2_buf = dma_alloc_coherent(&dev->pcidev->dev, cp->l2_buf_size, + &cp->l2_buf_map, + GFP_KERNEL | __GFP_COMP); + if (!cp->l2_buf) return -ENOMEM; - write_lock(&cnic_dev_lock); - list_add(&udev->list, &cnic_udev_list); - write_unlock(&cnic_dev_lock); - - pci_dev_get(udev->pdev); - - cp->udev = udev; - return 0; } -static int cnic_init_uio(struct cnic_dev *dev) -{ +static int cnic_alloc_uio(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; - struct cnic_uio_dev *udev = cp->udev; struct uio_info *uinfo; - int ret = 0; + int ret; - if (!udev) + uinfo = kzalloc(sizeof(*uinfo), GFP_ATOMIC); + if (!uinfo) return -ENOMEM; - uinfo = &udev->cnic_uinfo; - uinfo->mem[0].addr = dev->netdev->base_addr; uinfo->mem[0].internal_addr = dev->regview; uinfo->mem[0].size = dev->netdev->mem_end - dev->netdev->mem_start; @@ -980,7 +932,7 @@ static int cnic_init_uio(struct cnic_dev *dev) if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) { uinfo->mem[1].addr = (unsigned long) cp->status_blk.gen & - PAGE_MASK; + PAGE_MASK; if (cp->ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) uinfo->mem[1].size = BNX2_SBLK_MSIX_ALIGN_SIZE * 9; else @@ -997,12 +949,12 @@ static int cnic_init_uio(struct cnic_dev *dev) uinfo->mem[1].memtype = UIO_MEM_LOGICAL; - uinfo->mem[2].addr = (unsigned long) udev->l2_ring; - uinfo->mem[2].size = udev->l2_ring_size; + uinfo->mem[2].addr = (unsigned long) cp->l2_ring; + uinfo->mem[2].size = cp->l2_ring_size; uinfo->mem[2].memtype = UIO_MEM_LOGICAL; - uinfo->mem[3].addr = (unsigned long) udev->l2_buf; - uinfo->mem[3].size = udev->l2_buf_size; + uinfo->mem[3].addr = (unsigned long) cp->l2_buf; + uinfo->mem[3].size = cp->l2_buf_size; uinfo->mem[3].memtype = UIO_MEM_LOGICAL; uinfo->version = CNIC_MODULE_VERSION; @@ -1011,17 +963,16 @@ static int cnic_init_uio(struct cnic_dev *dev) uinfo->open = cnic_uio_open; uinfo->release = cnic_uio_close; - if (udev->uio_dev == -1) { - if (!uinfo->priv) { - uinfo->priv = udev; + uinfo->priv = dev; - ret = uio_register_device(&udev->pdev->dev, uinfo); - } - } else { - cnic_init_rings(dev); + ret = uio_register_device(&dev->pcidev->dev, uinfo); + if (ret) { + kfree(uinfo); + return ret; } - return ret; + cp->cnic_uinfo = uinfo; + return 0; } static int cnic_alloc_bnx2_resc(struct cnic_dev *dev) @@ -1042,11 +993,11 @@ static int cnic_alloc_bnx2_resc(struct cnic_dev *dev) if (ret) goto error; - ret = cnic_alloc_uio_rings(dev, 2); + ret = cnic_alloc_l2_rings(dev, 2); if (ret) goto error; - ret = cnic_init_uio(dev); + ret = cnic_alloc_uio(dev); if (ret) goto error; @@ -1077,7 +1028,7 @@ static int cnic_alloc_bnx2x_context(struct cnic_dev *dev) cp->ctx_blks = blks; cp->ctx_blk_size = ctx_blk_size; - if (!BNX2X_CHIP_IS_57710(cp->chip_id)) + if (BNX2X_CHIP_IS_E1H(cp->chip_id)) cp->ctx_align = 0; else cp->ctx_align = ctx_blk_size; @@ -1180,11 +1131,11 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev) cp->l2_rx_ring_size = 15; - ret = cnic_alloc_uio_rings(dev, 4); + ret = cnic_alloc_l2_rings(dev, 4); if (ret) goto error; - ret = cnic_init_uio(dev); + ret = cnic_alloc_uio(dev); if (ret) goto error; @@ -1678,11 +1629,10 @@ static int cnic_bnx2x_iscsi_ofld1(struct cnic_dev *dev, struct kwqe *wqes[], struct iscsi_kwqe_conn_offload1 *req1; struct iscsi_kwqe_conn_offload2 *req2; struct cnic_local *cp = dev->cnic_priv; - struct cnic_context *ctx; struct iscsi_kcqe kcqe; struct kcqe *cqes[1]; u32 l5_cid; - int ret = 0; + int ret; if (num < 2) { *work = num; @@ -1706,15 +1656,9 @@ static int cnic_bnx2x_iscsi_ofld1(struct cnic_dev *dev, struct kwqe *wqes[], kcqe.iscsi_conn_id = l5_cid; kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE; - ctx = &cp->ctx_tbl[l5_cid]; - if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags)) { - kcqe.completion_status = - ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY; - goto done; - } - if (atomic_inc_return(&cp->iscsi_conn) > dev->max_iscsi_conn) { atomic_dec(&cp->iscsi_conn); + ret = 0; goto done; } ret = cnic_alloc_bnx2x_conn_resc(dev, l5_cid); @@ -1764,14 +1708,25 @@ static int cnic_bnx2x_iscsi_update(struct cnic_dev *dev, struct kwqe *kwqe) return ret; } -static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid) +static int cnic_bnx2x_iscsi_destroy(struct cnic_dev *dev, struct kwqe *kwqe) { struct cnic_local *cp = dev->cnic_priv; - struct cnic_context *ctx = &cp->ctx_tbl[l5_cid]; + struct iscsi_kwqe_conn_destroy *req = + (struct iscsi_kwqe_conn_destroy *) kwqe; union l5cm_specific_data l5_data; - int ret; + u32 l5_cid = req->reserved0; + struct cnic_context *ctx = &cp->ctx_tbl[l5_cid]; + int ret = 0; + struct iscsi_kcqe kcqe; + struct kcqe *cqes[1]; u32 hw_cid, type; + if (!(ctx->ctx_flags & CTX_FL_OFFLD_START)) + goto skip_cfc_delete; + + while (!time_after(jiffies, ctx->timestamp + (2 * HZ))) + msleep(250); + init_waitqueue_head(&ctx->waitq); ctx->wait_cond = 0; memset(&l5_data, 0, sizeof(l5_data)); @@ -1787,43 +1742,11 @@ static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid) if (ret == 0) wait_event(ctx->waitq, ctx->wait_cond); - return ret; -} - -static int cnic_bnx2x_iscsi_destroy(struct cnic_dev *dev, struct kwqe *kwqe) -{ - struct cnic_local *cp = dev->cnic_priv; - struct iscsi_kwqe_conn_destroy *req = - (struct iscsi_kwqe_conn_destroy *) kwqe; - u32 l5_cid = req->reserved0; - struct cnic_context *ctx = &cp->ctx_tbl[l5_cid]; - int ret = 0; - struct iscsi_kcqe kcqe; - struct kcqe *cqes[1]; - - if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags)) - goto skip_cfc_delete; - - if (!time_after(jiffies, ctx->timestamp + (2 * HZ))) { - unsigned long delta = ctx->timestamp + (2 * HZ) - jiffies; - - if (delta > (2 * HZ)) - delta = 0; - - set_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags); - queue_delayed_work(cnic_wq, &cp->delete_task, delta); - goto destroy_reply; - } - - ret = cnic_bnx2x_destroy_ramrod(dev, l5_cid); - skip_cfc_delete: cnic_free_bnx2x_conn_resc(dev, l5_cid); atomic_dec(&cp->iscsi_conn); - clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags); -destroy_reply: memset(&kcqe, 0, sizeof(kcqe)); kcqe.op_code = ISCSI_KCQE_OPCODE_DESTROY_CONN; kcqe.iscsi_conn_id = l5_cid; @@ -2020,7 +1943,7 @@ static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[], ret = cnic_submit_kwqe_16(dev, L5CM_RAMROD_CMD_ID_TCP_CONNECT, kwqe1->cid, ISCSI_CONNECTION_TYPE, &l5_data); if (!ret) - set_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags); + ctx->ctx_flags |= CTX_FL_OFFLD_START; return ret; } @@ -2256,9 +2179,8 @@ static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info) static int cnic_l2_completion(struct cnic_local *cp) { u16 hw_cons, sw_cons; - struct cnic_uio_dev *udev = cp->udev; union eth_rx_cqe *cqe, *cqe_ring = (union eth_rx_cqe *) - (udev->l2_ring + (2 * BCM_PAGE_SIZE)); + (cp->l2_ring + (2 * BCM_PAGE_SIZE)); u32 cmd; int comp = 0; @@ -2304,8 +2226,7 @@ static void cnic_chk_pkt_rings(struct cnic_local *cp) cp->tx_cons = tx_cons; cp->rx_cons = rx_cons; - if (cp->udev) - uio_event_notify(&cp->udev->cnic_uinfo); + uio_event_notify(cp->cnic_uinfo); } if (comp) clear_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags); @@ -2406,22 +2327,6 @@ static inline void cnic_ack_bnx2x_int(struct cnic_dev *dev, u8 id, u8 storm, CNIC_WR(dev, hc_addr, (*(u32 *)&igu_ack)); } -static void cnic_ack_igu_sb(struct cnic_dev *dev, u8 igu_sb_id, u8 segment, - u16 index, u8 op, u8 update) -{ - struct igu_regular cmd_data; - u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id) * 8; - - cmd_data.sb_id_and_flags = - (index << IGU_REGULAR_SB_INDEX_SHIFT) | - (segment << IGU_REGULAR_SEGMENT_ACCESS_SHIFT) | - (update << IGU_REGULAR_BUPDATE_SHIFT) | - (op << IGU_REGULAR_ENABLE_INT_SHIFT); - - - CNIC_WR(dev, igu_addr, cmd_data.sb_id_and_flags); -} - static void cnic_ack_bnx2x_msix(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; @@ -2430,14 +2335,6 @@ static void cnic_ack_bnx2x_msix(struct cnic_dev *dev) IGU_INT_DISABLE, 0); } -static void cnic_ack_bnx2x_e2_msix(struct cnic_dev *dev) -{ - struct cnic_local *cp = dev->cnic_priv; - - cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF, 0, - IGU_INT_DISABLE, 0); -} - static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info) { u32 last_status = *info->status_idx_ptr; @@ -2469,12 +2366,8 @@ static void cnic_service_bnx2x_bh(unsigned long data) status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1); CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX); - if (BNX2X_CHIP_IS_E2(cp->chip_id)) - cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF, - status_idx, IGU_INT_ENABLE, 1); - else - cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID, - status_idx, IGU_INT_ENABLE, 1); + cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID, + status_idx, IGU_INT_ENABLE, 1); } static int cnic_service_bnx2x(void *data, void *status_blk) @@ -2495,7 +2388,8 @@ static void cnic_ulp_stop(struct cnic_dev *dev) struct cnic_local *cp = dev->cnic_priv; int if_type; - cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); + if (cp->cnic_uinfo) + cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) { struct cnic_ulp_ops *ulp_ops; @@ -2843,13 +2737,6 @@ static int cnic_cm_create(struct cnic_dev *dev, int ulp_type, u32 cid, if (l5_cid >= MAX_CM_SK_TBL_SZ) return -EINVAL; - if (cp->ctx_tbl) { - struct cnic_context *ctx = &cp->ctx_tbl[l5_cid]; - - if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags)) - return -EAGAIN; - } - csk1 = &cp->csk_tbl[l5_cid]; if (atomic_read(&csk1->ref_count)) return -EAGAIN; @@ -3401,32 +3288,6 @@ static void cnic_close_bnx2x_conn(struct cnic_sock *csk, u32 opcode) static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev) { - struct cnic_local *cp = dev->cnic_priv; - int i; - - if (!cp->ctx_tbl) - return; - - if (!netif_running(dev->netdev)) - return; - - for (i = 0; i < cp->max_cid_space; i++) { - struct cnic_context *ctx = &cp->ctx_tbl[i]; - - while (test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags)) - msleep(10); - - if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags)) - netdev_warn(dev->netdev, "CID %x not deleted\n", - ctx->cid); - } - - cancel_delayed_work(&cp->delete_task); - flush_workqueue(cnic_wq); - - if (atomic_read(&cp->iscsi_conn) != 0) - netdev_warn(dev->netdev, "%d iSCSI connections not destroyed\n", - atomic_read(&cp->iscsi_conn)); } static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev) @@ -3461,46 +3322,6 @@ static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev) return 0; } -static void cnic_delete_task(struct work_struct *work) -{ - struct cnic_local *cp; - struct cnic_dev *dev; - u32 i; - int need_resched = 0; - - cp = container_of(work, struct cnic_local, delete_task.work); - dev = cp->dev; - - for (i = 0; i < cp->max_cid_space; i++) { - struct cnic_context *ctx = &cp->ctx_tbl[i]; - - if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags) || - !test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags)) - continue; - - if (!time_after(jiffies, ctx->timestamp + (2 * HZ))) { - need_resched = 1; - continue; - } - - if (!test_and_clear_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags)) - continue; - - cnic_bnx2x_destroy_ramrod(dev, i); - - cnic_free_bnx2x_conn_resc(dev, i); - if (ctx->ulp_proto_id == CNIC_ULP_ISCSI) - atomic_dec(&cp->iscsi_conn); - - clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags); - } - - if (need_resched) - queue_delayed_work(cnic_wq, &cp->delete_task, - msecs_to_jiffies(10)); - -} - static int cnic_cm_open(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; @@ -3515,8 +3336,6 @@ static int cnic_cm_open(struct cnic_dev *dev) if (err) goto err_out; - INIT_DELAYED_WORK(&cp->delete_task, cnic_delete_task); - dev->cm_create = cnic_cm_create; dev->cm_destroy = cnic_cm_destroy; dev->cm_connect = cnic_cm_connect; @@ -3609,24 +3428,11 @@ static void cnic_free_irq(struct cnic_dev *dev) if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) { cp->disable_int_sync(dev); - tasklet_kill(&cp->cnic_irq_task); + tasklet_disable(&cp->cnic_irq_task); free_irq(ethdev->irq_arr[0].vector, dev); } } -static int cnic_request_irq(struct cnic_dev *dev) -{ - struct cnic_local *cp = dev->cnic_priv; - struct cnic_eth_dev *ethdev = cp->ethdev; - int err; - - err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0, "cnic", dev); - if (err) - tasklet_disable(&cp->cnic_irq_task); - - return err; -} - static int cnic_init_bnx2_irq(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; @@ -3647,10 +3453,12 @@ static int cnic_init_bnx2_irq(struct cnic_dev *dev) cp->last_status_idx = cp->status_blk.bnx2->status_idx; tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2_msix, (unsigned long) dev); - err = cnic_request_irq(dev); - if (err) + err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0, + "cnic", dev); + if (err) { + tasklet_disable(&cp->cnic_irq_task); return err; - + } while (cp->status_blk.bnx2->status_completion_producer_index && i < 10) { CNIC_WR(dev, BNX2_HC_COALESCE_NOW, @@ -3717,12 +3525,11 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; struct cnic_eth_dev *ethdev = cp->ethdev; - struct cnic_uio_dev *udev = cp->udev; u32 cid_addr, tx_cid, sb_id; u32 val, offset0, offset1, offset2, offset3; int i; struct tx_bd *txbd; - dma_addr_t buf_map, ring_map = udev->l2_ring_map; + dma_addr_t buf_map; struct status_block *s_blk = cp->status_blk.gen; sb_id = cp->status_blk_num; @@ -3764,18 +3571,18 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16); cnic_ctx_wr(dev, cid_addr, offset1, val); - txbd = (struct tx_bd *) udev->l2_ring; + txbd = (struct tx_bd *) cp->l2_ring; - buf_map = udev->l2_buf_map; + buf_map = cp->l2_buf_map; for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) { txbd->tx_bd_haddr_hi = (u64) buf_map >> 32; txbd->tx_bd_haddr_lo = (u64) buf_map & 0xffffffff; } - val = (u64) ring_map >> 32; + val = (u64) cp->l2_ring_map >> 32; cnic_ctx_wr(dev, cid_addr, offset2, val); txbd->tx_bd_haddr_hi = val; - val = (u64) ring_map & 0xffffffff; + val = (u64) cp->l2_ring_map & 0xffffffff; cnic_ctx_wr(dev, cid_addr, offset3, val); txbd->tx_bd_haddr_lo = val; } @@ -3784,12 +3591,10 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; struct cnic_eth_dev *ethdev = cp->ethdev; - struct cnic_uio_dev *udev = cp->udev; u32 cid_addr, sb_id, val, coal_reg, coal_val; int i; struct rx_bd *rxbd; struct status_block *s_blk = cp->status_blk.gen; - dma_addr_t ring_map = udev->l2_ring_map; sb_id = cp->status_blk_num; cnic_init_context(dev, 2); @@ -3823,22 +3628,22 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev) val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id); cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val); - rxbd = (struct rx_bd *) (udev->l2_ring + BCM_PAGE_SIZE); + rxbd = (struct rx_bd *) (cp->l2_ring + BCM_PAGE_SIZE); for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) { dma_addr_t buf_map; int n = (i % cp->l2_rx_ring_size) + 1; - buf_map = udev->l2_buf_map + (n * cp->l2_single_buf_size); + buf_map = cp->l2_buf_map + (n * cp->l2_single_buf_size); rxbd->rx_bd_len = cp->l2_single_buf_size; rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END; rxbd->rx_bd_haddr_hi = (u64) buf_map >> 32; rxbd->rx_bd_haddr_lo = (u64) buf_map & 0xffffffff; } - val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32; + val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) >> 32; cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val); rxbd->rx_bd_haddr_hi = val; - val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff; + val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) & 0xffffffff; cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val); rxbd->rx_bd_haddr_lo = val; @@ -4055,9 +3860,12 @@ static int cnic_init_bnx2x_irq(struct cnic_dev *dev) tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2x_bh, (unsigned long) dev); - if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) - err = cnic_request_irq(dev); - + if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) { + err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0, + "cnic", dev); + if (err) + tasklet_disable(&cp->cnic_irq_task); + } return err; } @@ -4100,9 +3908,8 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev, struct client_init_ramrod_data *data) { struct cnic_local *cp = dev->cnic_priv; - struct cnic_uio_dev *udev = cp->udev; - union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) udev->l2_ring; - dma_addr_t buf_map, ring_map = udev->l2_ring_map; + union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) cp->l2_ring; + dma_addr_t buf_map, ring_map = cp->l2_ring_map; struct host_sp_status_block *sb = cp->bnx2x_def_status_blk; int port = CNIC_PORT(cp); int i; @@ -4111,7 +3918,7 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev, memset(txbd, 0, BCM_PAGE_SIZE); - buf_map = udev->l2_buf_map; + buf_map = cp->l2_buf_map; for (i = 0; i < MAX_TX_DESC_CNT; i += 3, txbd += 3) { struct eth_tx_start_bd *start_bd = &txbd->start_bd; struct eth_tx_bd *reg_bd = &((txbd + 2)->reg_bd); @@ -4159,18 +3966,17 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, struct client_init_ramrod_data *data) { struct cnic_local *cp = dev->cnic_priv; - struct cnic_uio_dev *udev = cp->udev; - struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (udev->l2_ring + + struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (cp->l2_ring + BCM_PAGE_SIZE); struct eth_rx_cqe_next_page *rxcqe = (struct eth_rx_cqe_next_page *) - (udev->l2_ring + (2 * BCM_PAGE_SIZE)); + (cp->l2_ring + (2 * BCM_PAGE_SIZE)); struct host_sp_status_block *sb = cp->bnx2x_def_status_blk; int i; int port = CNIC_PORT(cp); int cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp)); int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli); u32 val; - dma_addr_t ring_map = udev->l2_ring_map; + dma_addr_t ring_map = cp->l2_ring_map; /* General data */ data->general.client_id = cli; @@ -4183,7 +3989,7 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, dma_addr_t buf_map; int n = (i % cp->l2_rx_ring_size) + 1; - buf_map = udev->l2_buf_map + (n * cp->l2_single_buf_size); + buf_map = cp->l2_buf_map + (n * cp->l2_single_buf_size); rxbd->addr_hi = cpu_to_le32((u64) buf_map >> 32); rxbd->addr_lo = cpu_to_le32(buf_map & 0xffffffff); } @@ -4236,7 +4042,7 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; - u32 base, base2, addr, val; + u32 base, addr, val; int port = CNIC_PORT(cp); dev->max_iscsi_conn = 0; @@ -4244,8 +4050,6 @@ static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev) if (base == 0) return; - base2 = CNIC_RD(dev, (CNIC_PATH(cp) ? MISC_REG_GENERIC_CR_1 : - MISC_REG_GENERIC_CR_0)); addr = BNX2X_SHMEM_ADDR(base, dev_info.port_hw_config[port].iscsi_mac_upper); @@ -4278,15 +4082,11 @@ static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev) val16 ^= 0x1e1e; dev->max_iscsi_conn = val16; } - if (BNX2X_CHIP_IS_E1H(cp->chip_id) || BNX2X_CHIP_IS_E2(cp->chip_id)) { + if (BNX2X_CHIP_IS_E1H(cp->chip_id)) { int func = CNIC_FUNC(cp); u32 mf_cfg_addr; - if (BNX2X_SHMEM2_HAS(base2, mf_cfg_addr)) - mf_cfg_addr = CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base2, - mf_cfg_addr)); - else - mf_cfg_addr = base + BNX2X_SHMEM_MF_BLK_OFFSET; + mf_cfg_addr = base + BNX2X_SHMEM_MF_BLK_OFFSET; addr = mf_cfg_addr + offsetof(struct mf_cfg, func_mf_config[func].e1hov_tag); @@ -4311,22 +4111,9 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev) struct cnic_eth_dev *ethdev = cp->ethdev; int func = CNIC_FUNC(cp), ret, i; u32 pfid; + struct host_hc_status_block_e1x *sb = cp->status_blk.gen; - if (BNX2X_CHIP_IS_E2(cp->chip_id)) { - u32 val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN_OVWR); - - if (!(val & 1)) - val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN); - else - val = (val >> 1) & 1; - - if (val) - cp->pfid = func >> 1; - else - cp->pfid = func & 0x6; - } else { - cp->pfid = func; - } + cp->pfid = func; pfid = cp->pfid; ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ, @@ -4341,21 +4128,10 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev) CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0); cp->kcq1.sw_prod_idx = 0; - if (BNX2X_CHIP_IS_E2(cp->chip_id)) { - struct host_hc_status_block_e2 *sb = cp->status_blk.gen; - - cp->kcq1.hw_prod_idx_ptr = - &sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS]; - cp->kcq1.status_idx_ptr = - &sb->sb.running_index[SM_RX_ID]; - } else { - struct host_hc_status_block_e1x *sb = cp->status_blk.gen; - - cp->kcq1.hw_prod_idx_ptr = - &sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS]; - cp->kcq1.status_idx_ptr = - &sb->sb.running_index[SM_RX_ID]; - } + cp->kcq1.hw_prod_idx_ptr = + &sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS]; + cp->kcq1.status_idx_ptr = + &sb->sb.running_index[SM_RX_ID]; cnic_get_bnx2x_iscsi_info(dev); @@ -4414,7 +4190,6 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev) static void cnic_init_rings(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; - struct cnic_uio_dev *udev = cp->udev; if (test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags)) return; @@ -4438,24 +4213,22 @@ static void cnic_init_rings(struct cnic_dev *dev) cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli); off = BAR_USTRORM_INTMEM + - (BNX2X_CHIP_IS_E2(cp->chip_id) ? - USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) : - USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli)); + USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli); for (i = 0; i < sizeof(struct ustorm_eth_rx_producers) / 4; i++) CNIC_WR(dev, off + i * 4, ((u32 *) &rx_prods)[i]); set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags); - data = udev->l2_buf; + data = cp->l2_buf; memset(data, 0, sizeof(*data)); cnic_init_bnx2x_tx_ring(dev, data); cnic_init_bnx2x_rx_ring(dev, data); - l5_data.phy_address.lo = udev->l2_buf_map & 0xffffffff; - l5_data.phy_address.hi = (u64) udev->l2_buf_map >> 32; + l5_data.phy_address.lo = cp->l2_buf_map & 0xffffffff; + l5_data.phy_address.hi = (u64) cp->l2_buf_map >> 32; type = (ETH_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE; @@ -4566,6 +4339,7 @@ static int cnic_start_hw(struct cnic_dev *dev) return -EALREADY; dev->regview = ethdev->io_base; + cp->chip_id = ethdev->chip_id; pci_dev_get(dev->pcidev); cp->func = PCI_FUNC(dev->pcidev->devfn); cp->status_blk.gen = ethdev->irq_arr[0].status_blk; @@ -4635,11 +4409,10 @@ static void cnic_stop_hw(struct cnic_dev *dev) /* Need to wait for the ring shutdown event to complete * before clearing the CNIC_UP flag. */ - while (cp->udev->uio_dev != -1 && i < 15) { + while (cp->uio_dev != -1 && i < 15) { msleep(100); i++; } - cnic_shutdown_rings(dev); clear_bit(CNIC_F_CNIC_UP, &dev->flags); rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], NULL); synchronize_rcu(); @@ -4688,6 +4461,7 @@ static struct cnic_dev *cnic_alloc_dev(struct net_device *dev, cp = cdev->cnic_priv; cp->dev = cdev; + cp->uio_dev = -1; cp->l2_single_buf_size = 0x400; cp->l2_rx_ring_size = 3; @@ -4742,7 +4516,6 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev) cp = cdev->cnic_priv; cp->ethdev = ethdev; cdev->pcidev = pdev; - cp->chip_id = ethdev->chip_id; cp->cnic_ops = &cnic_bnx2_ops; cp->start_hw = cnic_start_bnx2_hw; @@ -4797,7 +4570,6 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev) cp = cdev->cnic_priv; cp->ethdev = ethdev; cdev->pcidev = pdev; - cp->chip_id = ethdev->chip_id; cp->cnic_ops = &cnic_bnx2x_ops; cp->start_hw = cnic_start_bnx2x_hw; @@ -4809,10 +4581,7 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev) cp->stop_cm = cnic_cm_stop_bnx2x_hw; cp->enable_int = cnic_enable_bnx2x_int; cp->disable_int_sync = cnic_disable_bnx2x_int_sync; - if (BNX2X_CHIP_IS_E2(cp->chip_id)) - cp->ack_int = cnic_ack_bnx2x_e2_msix; - else - cp->ack_int = cnic_ack_bnx2x_msix; + cp->ack_int = cnic_ack_bnx2x_msix; cp->close_conn = cnic_close_bnx2x_conn; cp->next_idx = cnic_bnx2x_next_idx; cp->hw_idx = cnic_bnx2x_hw_idx; @@ -4920,7 +4689,6 @@ static struct notifier_block cnic_netdev_notifier = { static void cnic_release(void) { struct cnic_dev *dev; - struct cnic_uio_dev *udev; while (!list_empty(&cnic_dev_list)) { dev = list_entry(cnic_dev_list.next, struct cnic_dev, list); @@ -4934,11 +4702,6 @@ static void cnic_release(void) list_del_init(&dev->list); cnic_free_dev(dev); } - while (!list_empty(&cnic_udev_list)) { - udev = list_entry(cnic_udev_list.next, struct cnic_uio_dev, - list); - cnic_free_uio(udev); - } } static int __init cnic_init(void) @@ -4953,13 +4716,6 @@ static int __init cnic_init(void) return rc; } - cnic_wq = create_singlethread_workqueue("cnic_wq"); - if (!cnic_wq) { - cnic_release(); - unregister_netdevice_notifier(&cnic_netdev_notifier); - return -ENOMEM; - } - return 0; } @@ -4967,7 +4723,6 @@ static void __exit cnic_exit(void) { unregister_netdevice_notifier(&cnic_netdev_notifier); cnic_release(); - destroy_workqueue(cnic_wq); } module_init(cnic_init); diff --git a/trunk/drivers/net/cnic.h b/trunk/drivers/net/cnic.h index 6a4a0ae5cfe3..676d008509c6 100644 --- a/trunk/drivers/net/cnic.h +++ b/trunk/drivers/net/cnic.h @@ -168,9 +168,8 @@ struct cnic_context { wait_queue_head_t waitq; int wait_cond; unsigned long timestamp; - unsigned long ctx_flags; -#define CTX_FL_OFFLD_START 0 -#define CTX_FL_DELETE_WAIT 1 + u32 ctx_flags; +#define CTX_FL_OFFLD_START 0x00000001 u8 ulp_proto_id; union { struct cnic_iscsi *iscsi; @@ -195,23 +194,6 @@ struct iro { u16 size; }; -struct cnic_uio_dev { - struct uio_info cnic_uinfo; - u32 uio_dev; - - int l2_ring_size; - void *l2_ring; - dma_addr_t l2_ring_map; - - int l2_buf_size; - void *l2_buf; - dma_addr_t l2_buf_map; - - struct cnic_dev *dev; - struct pci_dev *pdev; - struct list_head list; -}; - struct cnic_local { spinlock_t cnic_ulp_lock; @@ -231,9 +213,14 @@ struct cnic_local { struct cnic_eth_dev *ethdev; - struct cnic_uio_dev *udev; - + void *l2_ring; + dma_addr_t l2_ring_map; + int l2_ring_size; int l2_rx_ring_size; + + void *l2_buf; + dma_addr_t l2_buf_map; + int l2_buf_size; int l2_single_buf_size; u16 *rx_cons_ptr; @@ -300,8 +287,6 @@ struct cnic_local { int hq_size; int num_cqs; - struct delayed_work delete_task; - struct cnic_ctx *ctx_arr; int ctx_blks; int ctx_blk_size; @@ -313,6 +298,9 @@ struct cnic_local { u32 pfid; u32 shmem_base; + u32 uio_dev; + struct uio_info *cnic_uinfo; + struct cnic_ops *cnic_ops; int (*start_hw)(struct cnic_dev *); void (*stop_hw)(struct cnic_dev *); @@ -372,35 +360,15 @@ struct bnx2x_bd_chain_next { #define BNX2X_ISCSI_PBL_NOT_CACHED 0xff #define BNX2X_ISCSI_PDU_HEADER_NOT_CACHED 0xff -#define BNX2X_CHIP_NUM_57710 0x164e #define BNX2X_CHIP_NUM_57711 0x164f #define BNX2X_CHIP_NUM_57711E 0x1650 -#define BNX2X_CHIP_NUM_57712 0x1662 -#define BNX2X_CHIP_NUM_57712E 0x1663 -#define BNX2X_CHIP_NUM_57713 0x1651 -#define BNX2X_CHIP_NUM_57713E 0x1652 - #define BNX2X_CHIP_NUM(x) (x >> 16) -#define BNX2X_CHIP_IS_57710(x) \ - (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57710) #define BNX2X_CHIP_IS_57711(x) \ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57711) #define BNX2X_CHIP_IS_57711E(x) \ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57711E) #define BNX2X_CHIP_IS_E1H(x) \ (BNX2X_CHIP_IS_57711(x) || BNX2X_CHIP_IS_57711E(x)) -#define BNX2X_CHIP_IS_57712(x) \ - (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57712) -#define BNX2X_CHIP_IS_57712E(x) \ - (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57712E) -#define BNX2X_CHIP_IS_57713(x) \ - (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713) -#define BNX2X_CHIP_IS_57713E(x) \ - (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713E) -#define BNX2X_CHIP_IS_E2(x) \ - (BNX2X_CHIP_IS_57712(x) || BNX2X_CHIP_IS_57712E(x) || \ - BNX2X_CHIP_IS_57713(x) || BNX2X_CHIP_IS_57713E(x)) - #define IS_E1H_OFFSET BNX2X_CHIP_IS_E1H(cp->chip_id) #define BNX2X_RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_bd)) @@ -429,8 +397,6 @@ struct bnx2x_bd_chain_next { #define CNIC_PORT(cp) ((cp)->pfid & 1) #define CNIC_FUNC(cp) ((cp)->func) -#define CNIC_PATH(cp) (!BNX2X_CHIP_IS_E2(cp->chip_id) ? 0 :\ - (CNIC_FUNC(cp) & 1)) #define CNIC_E1HVN(cp) ((cp)->pfid >> 1) #define BNX2X_HW_CID(cp, x) ((CNIC_PORT(cp) << 23) | \ diff --git a/trunk/drivers/net/cnic_if.h b/trunk/drivers/net/cnic_if.h index 0dbeaec4f03a..98ebac52013e 100644 --- a/trunk/drivers/net/cnic_if.h +++ b/trunk/drivers/net/cnic_if.h @@ -12,8 +12,8 @@ #ifndef CNIC_IF_H #define CNIC_IF_H -#define CNIC_MODULE_VERSION "2.2.6" -#define CNIC_MODULE_RELDATE "Oct 12, 2010" +#define CNIC_MODULE_VERSION "2.2.5" +#define CNIC_MODULE_RELDATE "September 29, 2010" #define CNIC_ULP_RDMA 0 #define CNIC_ULP_ISCSI 1 diff --git a/trunk/drivers/net/cxgb4vf/t4vf_common.h b/trunk/drivers/net/cxgb4vf/t4vf_common.h index 873cb7d86c57..5c7bde7f9bae 100644 --- a/trunk/drivers/net/cxgb4vf/t4vf_common.h +++ b/trunk/drivers/net/cxgb4vf/t4vf_common.h @@ -132,15 +132,15 @@ struct rss_params { unsigned int mode; /* RSS mode */ union { struct { - unsigned int synmapen:1; /* SYN Map Enable */ - unsigned int syn4tupenipv6:1; /* enable hashing 4-tuple IPv6 SYNs */ - unsigned int syn2tupenipv6:1; /* enable hashing 2-tuple IPv6 SYNs */ - unsigned int syn4tupenipv4:1; /* enable hashing 4-tuple IPv4 SYNs */ - unsigned int syn2tupenipv4:1; /* enable hashing 2-tuple IPv4 SYNs */ - unsigned int ofdmapen:1; /* Offload Map Enable */ - unsigned int tnlmapen:1; /* Tunnel Map Enable */ - unsigned int tnlalllookup:1; /* Tunnel All Lookup */ - unsigned int hashtoeplitz:1; /* use Toeplitz hash */ + int synmapen:1; /* SYN Map Enable */ + int syn4tupenipv6:1; /* enable hashing 4-tuple IPv6 SYNs */ + int syn2tupenipv6:1; /* enable hashing 2-tuple IPv6 SYNs */ + int syn4tupenipv4:1; /* enable hashing 4-tuple IPv4 SYNs */ + int syn2tupenipv4:1; /* enable hashing 2-tuple IPv4 SYNs */ + int ofdmapen:1; /* Offload Map Enable */ + int tnlmapen:1; /* Tunnel Map Enable */ + int tnlalllookup:1; /* Tunnel All Lookup */ + int hashtoeplitz:1; /* use Toeplitz hash */ } basicvirtual; } u; }; @@ -151,10 +151,10 @@ struct rss_params { union rss_vi_config { struct { u16 defaultq; /* Ingress Queue ID for !tnlalllookup */ - unsigned int ip6fourtupen:1; /* hash 4-tuple IPv6 ingress packets */ - unsigned int ip6twotupen:1; /* hash 2-tuple IPv6 ingress packets */ - unsigned int ip4fourtupen:1; /* hash 4-tuple IPv4 ingress packets */ - unsigned int ip4twotupen:1; /* hash 2-tuple IPv4 ingress packets */ + int ip6fourtupen:1; /* hash 4-tuple IPv6 ingress packets */ + int ip6twotupen:1; /* hash 2-tuple IPv6 ingress packets */ + int ip4fourtupen:1; /* hash 4-tuple IPv4 ingress packets */ + int ip4twotupen:1; /* hash 2-tuple IPv4 ingress packets */ int udpen; /* hash 4-tuple UDP ingress packets */ } basicvirtual; }; diff --git a/trunk/drivers/net/dnet.c b/trunk/drivers/net/dnet.c index 9d8a20b72fa9..7c075756611a 100644 --- a/trunk/drivers/net/dnet.c +++ b/trunk/drivers/net/dnet.c @@ -27,7 +27,7 @@ #undef DEBUG /* function for reading internal MAC register */ -static u16 dnet_readw_mac(struct dnet *bp, u16 reg) +u16 dnet_readw_mac(struct dnet *bp, u16 reg) { u16 data_read; @@ -46,7 +46,7 @@ static u16 dnet_readw_mac(struct dnet *bp, u16 reg) } /* function for writing internal MAC register */ -static void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val) +void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val) { /* load data to write */ dnet_writel(bp, val, MACREG_DATA); @@ -63,11 +63,11 @@ static void __dnet_set_hwaddr(struct dnet *bp) { u16 tmp; - tmp = be16_to_cpup((__be16 *)bp->dev->dev_addr); + tmp = cpu_to_be16(*((u16 *) bp->dev->dev_addr)); dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG, tmp); - tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 2)); + tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 2))); dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG, tmp); - tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 4)); + tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 4))); dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp); } @@ -89,11 +89,11 @@ static void __devinit dnet_get_hwaddr(struct dnet *bp) * Mac_addr[15:0]). */ tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG); - *((__be16 *)addr) = cpu_to_be16(tmp); + *((u16 *) addr) = be16_to_cpu(tmp); tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG); - *((__be16 *)(addr + 2)) = cpu_to_be16(tmp); + *((u16 *) (addr + 2)) = be16_to_cpu(tmp); tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG); - *((__be16 *)(addr + 4)) = cpu_to_be16(tmp); + *((u16 *) (addr + 4)) = be16_to_cpu(tmp); if (is_valid_ether_addr(addr)) memcpy(bp->dev->dev_addr, addr, sizeof(addr)); @@ -361,7 +361,7 @@ static int dnet_mii_init(struct dnet *bp) } /* For Neptune board: LINK1000 as Link LED and TX as activity LED */ -static int dnet_phy_marvell_fixup(struct phy_device *phydev) +int dnet_phy_marvell_fixup(struct phy_device *phydev) { return phy_write(phydev, 0x18, 0x4148); } diff --git a/trunk/drivers/net/e1000e/ethtool.c b/trunk/drivers/net/e1000e/ethtool.c index 8984d165a39b..b7f15b3f0e03 100644 --- a/trunk/drivers/net/e1000e/ethtool.c +++ b/trunk/drivers/net/e1000e/ethtool.c @@ -1717,6 +1717,13 @@ static void e1000_diag_test(struct net_device *netdev, e_info("offline testing starting\n"); + /* + * Link test performed before hardware reset so autoneg doesn't + * interfere with test result + */ + if (e1000_link_test(adapter, &data[4])) + eth_test->flags |= ETH_TEST_FL_FAILED; + if (if_running) /* indicate we're in test mode */ dev_close(netdev); @@ -1740,19 +1747,15 @@ static void e1000_diag_test(struct net_device *netdev, if (e1000_loopback_test(adapter, &data[3])) eth_test->flags |= ETH_TEST_FL_FAILED; - /* force this routine to wait until autoneg complete/timeout */ - adapter->hw.phy.autoneg_wait_to_complete = 1; - e1000e_reset(adapter); - adapter->hw.phy.autoneg_wait_to_complete = 0; - - if (e1000_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; - /* restore speed, duplex, autoneg settings */ adapter->hw.phy.autoneg_advertised = autoneg_advertised; adapter->hw.mac.forced_speed_duplex = forced_speed_duplex; adapter->hw.mac.autoneg = autoneg; + + /* force this routine to wait until autoneg complete/timeout */ + adapter->hw.phy.autoneg_wait_to_complete = 1; e1000e_reset(adapter); + adapter->hw.phy.autoneg_wait_to_complete = 0; clear_bit(__E1000_TESTING, &adapter->state); if (if_running) diff --git a/trunk/drivers/net/igb/igb.h b/trunk/drivers/net/igb/igb.h index edab9c442399..44e0ff1494e0 100644 --- a/trunk/drivers/net/igb/igb.h +++ b/trunk/drivers/net/igb/igb.h @@ -159,7 +159,6 @@ struct igb_tx_queue_stats { u64 packets; u64 bytes; u64 restart_queue; - u64 restart_queue2; }; struct igb_rx_queue_stats { @@ -211,14 +210,11 @@ struct igb_ring { /* TX */ struct { struct igb_tx_queue_stats tx_stats; - struct u64_stats_sync tx_syncp; - struct u64_stats_sync tx_syncp2; bool detect_tx_hung; }; /* RX */ struct { struct igb_rx_queue_stats rx_stats; - struct u64_stats_sync rx_syncp; u32 rx_buffer_len; }; }; @@ -292,9 +288,6 @@ struct igb_adapter { struct timecompare compare; struct hwtstamp_config hwtstamp_config; - spinlock_t stats64_lock; - struct rtnl_link_stats64 stats64; - /* structs defined in e1000_hw.h */ struct e1000_hw hw; struct e1000_hw_stats stats; @@ -364,7 +357,7 @@ extern netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *, struct igb_ring *); extern void igb_unmap_and_free_tx_resource(struct igb_ring *, struct igb_buffer *); extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int); -extern void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *); +extern void igb_update_stats(struct igb_adapter *); extern bool igb_has_link(struct igb_adapter *adapter); extern void igb_set_ethtool_ops(struct net_device *); extern void igb_power_up_link(struct igb_adapter *); diff --git a/trunk/drivers/net/igb/igb_ethtool.c b/trunk/drivers/net/igb/igb_ethtool.c index a70e16bcfa7e..26bf6a13d1c1 100644 --- a/trunk/drivers/net/igb/igb_ethtool.c +++ b/trunk/drivers/net/igb/igb_ethtool.c @@ -90,8 +90,8 @@ static const struct igb_stats igb_gstrings_stats[] = { #define IGB_NETDEV_STAT(_net_stat) { \ .stat_string = __stringify(_net_stat), \ - .sizeof_stat = FIELD_SIZEOF(struct rtnl_link_stats64, _net_stat), \ - .stat_offset = offsetof(struct rtnl_link_stats64, _net_stat) \ + .sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \ + .stat_offset = offsetof(struct net_device_stats, _net_stat) \ } static const struct igb_stats igb_gstrings_net_stats[] = { IGB_NETDEV_STAT(rx_errors), @@ -111,9 +111,8 @@ static const struct igb_stats igb_gstrings_net_stats[] = { (sizeof(igb_gstrings_net_stats) / sizeof(struct igb_stats)) #define IGB_RX_QUEUE_STATS_LEN \ (sizeof(struct igb_rx_queue_stats) / sizeof(u64)) - -#define IGB_TX_QUEUE_STATS_LEN 3 /* packets, bytes, restart_queue */ - +#define IGB_TX_QUEUE_STATS_LEN \ + (sizeof(struct igb_tx_queue_stats) / sizeof(u64)) #define IGB_QUEUE_STATS_LEN \ ((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues * \ IGB_RX_QUEUE_STATS_LEN) + \ @@ -2071,14 +2070,12 @@ static void igb_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) { struct igb_adapter *adapter = netdev_priv(netdev); - struct rtnl_link_stats64 *net_stats = &adapter->stats64; - unsigned int start; - struct igb_ring *ring; - int i, j; + struct net_device_stats *net_stats = &netdev->stats; + u64 *queue_stat; + int i, j, k; char *p; - spin_lock(&adapter->stats64_lock); - igb_update_stats(adapter, net_stats); + igb_update_stats(adapter); for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { p = (char *)adapter + igb_gstrings_stats[i].stat_offset; @@ -2091,36 +2088,15 @@ static void igb_get_ethtool_stats(struct net_device *netdev, sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } for (j = 0; j < adapter->num_tx_queues; j++) { - u64 restart2; - - ring = adapter->tx_ring[j]; - do { - start = u64_stats_fetch_begin_bh(&ring->tx_syncp); - data[i] = ring->tx_stats.packets; - data[i+1] = ring->tx_stats.bytes; - data[i+2] = ring->tx_stats.restart_queue; - } while (u64_stats_fetch_retry_bh(&ring->tx_syncp, start)); - do { - start = u64_stats_fetch_begin_bh(&ring->tx_syncp2); - restart2 = ring->tx_stats.restart_queue2; - } while (u64_stats_fetch_retry_bh(&ring->tx_syncp2, start)); - data[i+2] += restart2; - - i += IGB_TX_QUEUE_STATS_LEN; + queue_stat = (u64 *)&adapter->tx_ring[j]->tx_stats; + for (k = 0; k < IGB_TX_QUEUE_STATS_LEN; k++, i++) + data[i] = queue_stat[k]; } for (j = 0; j < adapter->num_rx_queues; j++) { - ring = adapter->rx_ring[j]; - do { - start = u64_stats_fetch_begin_bh(&ring->rx_syncp); - data[i] = ring->rx_stats.packets; - data[i+1] = ring->rx_stats.bytes; - data[i+2] = ring->rx_stats.drops; - data[i+3] = ring->rx_stats.csum_err; - data[i+4] = ring->rx_stats.alloc_failed; - } while (u64_stats_fetch_retry_bh(&ring->rx_syncp, start)); - i += IGB_RX_QUEUE_STATS_LEN; + queue_stat = (u64 *)&adapter->rx_ring[j]->rx_stats; + for (k = 0; k < IGB_RX_QUEUE_STATS_LEN; k++, i++) + data[i] = queue_stat[k]; } - spin_unlock(&adapter->stats64_lock); } static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data) diff --git a/trunk/drivers/net/igb/igb_main.c b/trunk/drivers/net/igb/igb_main.c index b8dccc0ac089..55edcb74abf4 100644 --- a/trunk/drivers/net/igb/igb_main.c +++ b/trunk/drivers/net/igb/igb_main.c @@ -96,6 +96,7 @@ static int igb_setup_all_rx_resources(struct igb_adapter *); static void igb_free_all_tx_resources(struct igb_adapter *); static void igb_free_all_rx_resources(struct igb_adapter *); static void igb_setup_mrqc(struct igb_adapter *); +void igb_update_stats(struct igb_adapter *); static int igb_probe(struct pci_dev *, const struct pci_device_id *); static void __devexit igb_remove(struct pci_dev *pdev); static int igb_sw_init(struct igb_adapter *); @@ -112,8 +113,7 @@ static void igb_update_phy_info(unsigned long); static void igb_watchdog(unsigned long); static void igb_watchdog_task(struct work_struct *); static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *); -static struct rtnl_link_stats64 *igb_get_stats64(struct net_device *dev, - struct rtnl_link_stats64 *stats); +static struct net_device_stats *igb_get_stats(struct net_device *); static int igb_change_mtu(struct net_device *, int); static int igb_set_mac(struct net_device *, void *); static void igb_set_uta(struct igb_adapter *adapter); @@ -1536,9 +1536,7 @@ void igb_down(struct igb_adapter *adapter) netif_carrier_off(netdev); /* record the stats before reset*/ - spin_lock(&adapter->stats64_lock); - igb_update_stats(adapter, &adapter->stats64); - spin_unlock(&adapter->stats64_lock); + igb_update_stats(adapter); adapter->link_speed = 0; adapter->link_duplex = 0; @@ -1691,7 +1689,7 @@ static const struct net_device_ops igb_netdev_ops = { .ndo_open = igb_open, .ndo_stop = igb_close, .ndo_start_xmit = igb_xmit_frame_adv, - .ndo_get_stats64 = igb_get_stats64, + .ndo_get_stats = igb_get_stats, .ndo_set_rx_mode = igb_set_rx_mode, .ndo_set_multicast_list = igb_set_rx_mode, .ndo_set_mac_address = igb_set_mac, @@ -2278,7 +2276,6 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; - spin_lock_init(&adapter->stats64_lock); #ifdef CONFIG_PCI_IOV if (hw->mac.type == e1000_82576) adapter->vfs_allocated_count = (max_vfs > 7) ? 7 : max_vfs; @@ -3486,9 +3483,7 @@ static void igb_watchdog_task(struct work_struct *work) } } - spin_lock(&adapter->stats64_lock); - igb_update_stats(adapter, &adapter->stats64); - spin_unlock(&adapter->stats64_lock); + igb_update_stats(adapter); for (i = 0; i < adapter->num_tx_queues; i++) { struct igb_ring *tx_ring = adapter->tx_ring[i]; @@ -3555,8 +3550,6 @@ static void igb_update_ring_itr(struct igb_q_vector *q_vector) int new_val = q_vector->itr_val; int avg_wire_size = 0; struct igb_adapter *adapter = q_vector->adapter; - struct igb_ring *ring; - unsigned int packets; /* For non-gigabit speeds, just fix the interrupt rate at 4000 * ints/sec - ITR timer value of 120 ticks. @@ -3566,21 +3559,16 @@ static void igb_update_ring_itr(struct igb_q_vector *q_vector) goto set_itr_val; } - ring = q_vector->rx_ring; - if (ring) { - packets = ACCESS_ONCE(ring->total_packets); - - if (packets) - avg_wire_size = ring->total_bytes / packets; + if (q_vector->rx_ring && q_vector->rx_ring->total_packets) { + struct igb_ring *ring = q_vector->rx_ring; + avg_wire_size = ring->total_bytes / ring->total_packets; } - ring = q_vector->tx_ring; - if (ring) { - packets = ACCESS_ONCE(ring->total_packets); - - if (packets) - avg_wire_size = max_t(u32, avg_wire_size, - ring->total_bytes / packets); + if (q_vector->tx_ring && q_vector->tx_ring->total_packets) { + struct igb_ring *ring = q_vector->tx_ring; + avg_wire_size = max_t(u32, avg_wire_size, + (ring->total_bytes / + ring->total_packets)); } /* if avg_wire_size isn't set no work was done */ @@ -4089,11 +4077,7 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, int size) /* A reprieve! */ netif_wake_subqueue(netdev, tx_ring->queue_index); - - u64_stats_update_begin(&tx_ring->tx_syncp2); - tx_ring->tx_stats.restart_queue2++; - u64_stats_update_end(&tx_ring->tx_syncp2); - + tx_ring->tx_stats.restart_queue++; return 0; } @@ -4230,22 +4214,16 @@ static void igb_reset_task(struct work_struct *work) } /** - * igb_get_stats64 - Get System Network Statistics + * igb_get_stats - Get System Network Statistics * @netdev: network interface device structure - * @stats: rtnl_link_stats64 pointer * + * Returns the address of the device statistics structure. + * The statistics are actually updated from the timer callback. **/ -static struct rtnl_link_stats64 *igb_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *stats) +static struct net_device_stats *igb_get_stats(struct net_device *netdev) { - struct igb_adapter *adapter = netdev_priv(netdev); - - spin_lock(&adapter->stats64_lock); - igb_update_stats(adapter, &adapter->stats64); - memcpy(stats, &adapter->stats64, sizeof(*stats)); - spin_unlock(&adapter->stats64_lock); - - return stats; + /* only return the current stats */ + return &netdev->stats; } /** @@ -4327,17 +4305,15 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) * @adapter: board private structure **/ -void igb_update_stats(struct igb_adapter *adapter, - struct rtnl_link_stats64 *net_stats) +void igb_update_stats(struct igb_adapter *adapter) { + struct net_device_stats *net_stats = igb_get_stats(adapter->netdev); struct e1000_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; u32 reg, mpc; u16 phy_tmp; int i; u64 bytes, packets; - unsigned int start; - u64 _bytes, _packets; #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF @@ -4355,17 +4331,10 @@ void igb_update_stats(struct igb_adapter *adapter, for (i = 0; i < adapter->num_rx_queues; i++) { u32 rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0x0FFF; struct igb_ring *ring = adapter->rx_ring[i]; - ring->rx_stats.drops += rqdpc_tmp; net_stats->rx_fifo_errors += rqdpc_tmp; - - do { - start = u64_stats_fetch_begin_bh(&ring->rx_syncp); - _bytes = ring->rx_stats.bytes; - _packets = ring->rx_stats.packets; - } while (u64_stats_fetch_retry_bh(&ring->rx_syncp, start)); - bytes += _bytes; - packets += _packets; + bytes += ring->rx_stats.bytes; + packets += ring->rx_stats.packets; } net_stats->rx_bytes = bytes; @@ -4375,13 +4344,8 @@ void igb_update_stats(struct igb_adapter *adapter, packets = 0; for (i = 0; i < adapter->num_tx_queues; i++) { struct igb_ring *ring = adapter->tx_ring[i]; - do { - start = u64_stats_fetch_begin_bh(&ring->tx_syncp); - _bytes = ring->tx_stats.bytes; - _packets = ring->tx_stats.packets; - } while (u64_stats_fetch_retry_bh(&ring->tx_syncp, start)); - bytes += _bytes; - packets += _packets; + bytes += ring->tx_stats.bytes; + packets += ring->tx_stats.packets; } net_stats->tx_bytes = bytes; net_stats->tx_packets = packets; @@ -5433,10 +5397,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) && !(test_bit(__IGB_DOWN, &adapter->state))) { netif_wake_subqueue(netdev, tx_ring->queue_index); - - u64_stats_update_begin(&tx_ring->tx_syncp); tx_ring->tx_stats.restart_queue++; - u64_stats_update_end(&tx_ring->tx_syncp); } } @@ -5476,10 +5437,8 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) } tx_ring->total_bytes += total_bytes; tx_ring->total_packets += total_packets; - u64_stats_update_begin(&tx_ring->tx_syncp); tx_ring->tx_stats.bytes += total_bytes; tx_ring->tx_stats.packets += total_packets; - u64_stats_update_end(&tx_ring->tx_syncp); return count < tx_ring->count; } @@ -5521,11 +5480,9 @@ static inline void igb_rx_checksum_adv(struct igb_ring *ring, * packets, (aka let the stack check the crc32c) */ if ((skb->len == 60) && - (ring->flags & IGB_RING_FLAG_RX_SCTP_CSUM)) { - u64_stats_update_begin(&ring->rx_syncp); + (ring->flags & IGB_RING_FLAG_RX_SCTP_CSUM)) ring->rx_stats.csum_err++; - u64_stats_update_end(&ring->rx_syncp); - } + /* let the stack verify checksum errors */ return; } @@ -5712,10 +5669,8 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector, rx_ring->total_packets += total_packets; rx_ring->total_bytes += total_bytes; - u64_stats_update_begin(&rx_ring->rx_syncp); rx_ring->rx_stats.packets += total_packets; rx_ring->rx_stats.bytes += total_bytes; - u64_stats_update_end(&rx_ring->rx_syncp); return cleaned; } @@ -5743,10 +5698,8 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count) if ((bufsz < IGB_RXBUFFER_1024) && !buffer_info->page_dma) { if (!buffer_info->page) { buffer_info->page = netdev_alloc_page(netdev); - if (unlikely(!buffer_info->page)) { - u64_stats_update_begin(&rx_ring->rx_syncp); + if (!buffer_info->page) { rx_ring->rx_stats.alloc_failed++; - u64_stats_update_end(&rx_ring->rx_syncp); goto no_buffers; } buffer_info->page_offset = 0; @@ -5761,9 +5714,7 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count) if (dma_mapping_error(rx_ring->dev, buffer_info->page_dma)) { buffer_info->page_dma = 0; - u64_stats_update_begin(&rx_ring->rx_syncp); rx_ring->rx_stats.alloc_failed++; - u64_stats_update_end(&rx_ring->rx_syncp); goto no_buffers; } } @@ -5771,10 +5722,8 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count) skb = buffer_info->skb; if (!skb) { skb = netdev_alloc_skb_ip_align(netdev, bufsz); - if (unlikely(!skb)) { - u64_stats_update_begin(&rx_ring->rx_syncp); + if (!skb) { rx_ring->rx_stats.alloc_failed++; - u64_stats_update_end(&rx_ring->rx_syncp); goto no_buffers; } @@ -5788,9 +5737,7 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count) if (dma_mapping_error(rx_ring->dev, buffer_info->dma)) { buffer_info->dma = 0; - u64_stats_update_begin(&rx_ring->rx_syncp); rx_ring->rx_stats.alloc_failed++; - u64_stats_update_end(&rx_ring->rx_syncp); goto no_buffers; } } @@ -6168,13 +6115,6 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx) mac->autoneg = 0; - /* Fiber NIC's only allow 1000 Gbps Full duplex */ - if ((adapter->hw.phy.media_type == e1000_media_type_internal_serdes) && - spddplx != (SPEED_1000 + DUPLEX_FULL)) { - dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); - return -EINVAL; - } - switch (spddplx) { case SPEED_10 + DUPLEX_HALF: mac->forced_speed_duplex = ADVERTISE_10_HALF; diff --git a/trunk/drivers/net/igbvf/netdev.c b/trunk/drivers/net/igbvf/netdev.c index 6693323a6cf5..265501348f33 100644 --- a/trunk/drivers/net/igbvf/netdev.c +++ b/trunk/drivers/net/igbvf/netdev.c @@ -41,12 +41,14 @@ #include #include #include +#include #include "igbvf.h" #define DRV_VERSION "1.0.0-k0" char igbvf_driver_name[] = "igbvf"; const char igbvf_driver_version[] = DRV_VERSION; +static struct pm_qos_request_list igbvf_driver_pm_qos_req; static const char igbvf_driver_string[] = "Intel(R) Virtual Function Network Driver"; static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation."; @@ -2902,6 +2904,8 @@ static int __init igbvf_init_module(void) printk(KERN_INFO "%s\n", igbvf_copyright); ret = pci_register_driver(&igbvf_driver); + pm_qos_add_request(&igbvf_driver_pm_qos_req, PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); return ret; } @@ -2916,6 +2920,7 @@ module_init(igbvf_init_module); static void __exit igbvf_exit_module(void) { pci_unregister_driver(&igbvf_driver); + pm_qos_remove_request(&igbvf_driver_pm_qos_req); } module_exit(igbvf_exit_module); diff --git a/trunk/drivers/net/ixgbe/ixgbe_82599.c b/trunk/drivers/net/ixgbe/ixgbe_82599.c index 0bd8fbb5bfd0..e80657c75506 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_82599.c +++ b/trunk/drivers/net/ixgbe/ixgbe_82599.c @@ -39,20 +39,20 @@ #define IXGBE_82599_MC_TBL_SIZE 128 #define IXGBE_82599_VFT_TBL_SIZE 128 -static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); -static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); -static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); -static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, - ixgbe_link_speed speed, - bool autoneg, - bool autoneg_wait_to_complete); +void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); +void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); +void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); +s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + bool autoneg, + bool autoneg_wait_to_complete); static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); -static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, - bool autoneg_wait_to_complete); -static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, +s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, + bool autoneg_wait_to_complete); +s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); @@ -369,7 +369,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) * Configures link settings based on values in the ixgbe_hw struct. * Restarts the link. Performs autonegotiation if needed. **/ -static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, +s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, bool autoneg_wait_to_complete) { u32 autoc_reg; @@ -418,7 +418,7 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, * PHY states. This includes selectively shutting down the Tx * laser on the PHY, effectively halting physical link. **/ -static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) +void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) { u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); @@ -437,7 +437,7 @@ static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) * PHY states. This includes selectively turning on the Tx * laser on the PHY, effectively starting physical link. **/ -static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) +void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) { u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); @@ -460,7 +460,7 @@ static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) * end. This is consistent with true clause 37 autoneg, which also * involves a loss of signal. **/ -static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) +void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) { hw_dbg(hw, "ixgbe_flap_tx_laser_multispeed_fiber\n"); @@ -729,7 +729,7 @@ static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, * * Set the link speed in the AUTOC register and restarts link. **/ -static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, +s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { @@ -1414,6 +1414,92 @@ s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr) return 0; } +/** + * ixgbe_atr_set_src_ipv6_82599 - Sets the source IPv6 address + * @input: input stream to modify + * @src_addr_1: the first 4 bytes of the IP address to load + * @src_addr_2: the second 4 bytes of the IP address to load + * @src_addr_3: the third 4 bytes of the IP address to load + * @src_addr_4: the fourth 4 bytes of the IP address to load + **/ +s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input, + u32 src_addr_1, u32 src_addr_2, + u32 src_addr_3, u32 src_addr_4) +{ + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] = + (src_addr_4 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] = + (src_addr_4 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] = src_addr_4 >> 24; + + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4] = src_addr_3 & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] = + (src_addr_3 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] = + (src_addr_3 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] = src_addr_3 >> 24; + + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8] = src_addr_2 & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] = + (src_addr_2 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] = + (src_addr_2 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] = src_addr_2 >> 24; + + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12] = src_addr_1 & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] = + (src_addr_1 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] = + (src_addr_1 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] = src_addr_1 >> 24; + + return 0; +} + +/** + * ixgbe_atr_set_dst_ipv6_82599 - Sets the destination IPv6 address + * @input: input stream to modify + * @dst_addr_1: the first 4 bytes of the IP address to load + * @dst_addr_2: the second 4 bytes of the IP address to load + * @dst_addr_3: the third 4 bytes of the IP address to load + * @dst_addr_4: the fourth 4 bytes of the IP address to load + **/ +s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input, + u32 dst_addr_1, u32 dst_addr_2, + u32 dst_addr_3, u32 dst_addr_4) +{ + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] = + (dst_addr_4 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] = + (dst_addr_4 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] = dst_addr_4 >> 24; + + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4] = dst_addr_3 & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] = + (dst_addr_3 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] = + (dst_addr_3 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] = dst_addr_3 >> 24; + + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8] = dst_addr_2 & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] = + (dst_addr_2 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] = + (dst_addr_2 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] = dst_addr_2 >> 24; + + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12] = dst_addr_1 & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] = + (dst_addr_1 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] = + (dst_addr_1 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] = dst_addr_1 >> 24; + + return 0; +} + /** * ixgbe_atr_set_src_port_82599 - Sets the source port * @input: input stream to modify @@ -1453,6 +1539,19 @@ s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte) return 0; } +/** + * ixgbe_atr_set_vm_pool_82599 - Sets the Virtual Machine pool + * @input: input stream to modify + * @vm_pool: the Virtual Machine pool to load + **/ +s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, + u8 vm_pool) +{ + input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool; + + return 0; +} + /** * ixgbe_atr_set_l4type_82599 - Sets the layer 4 packet type * @input: input stream to modify @@ -1545,6 +1644,41 @@ static s32 ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input, return 0; } +/** + * ixgbe_atr_get_dst_ipv6_82599 - Gets the destination IPv6 address + * @input: input stream to search + * @dst_addr_1: the first 4 bytes of the IP address to load + * @dst_addr_2: the second 4 bytes of the IP address to load + * @dst_addr_3: the third 4 bytes of the IP address to load + * @dst_addr_4: the fourth 4 bytes of the IP address to load + **/ +s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input, + u32 *dst_addr_1, u32 *dst_addr_2, + u32 *dst_addr_3, u32 *dst_addr_4) +{ + *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12]; + *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] << 8; + *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] << 16; + *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] << 24; + + *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8]; + *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] << 8; + *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] << 16; + *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] << 24; + + *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4]; + *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] << 8; + *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] << 16; + *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] << 24; + + *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET]; + *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] << 8; + *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] << 16; + *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] << 24; + + return 0; +} + /** * ixgbe_atr_get_src_port_82599 - Gets the source port * @input: input stream to modify @@ -1597,6 +1731,19 @@ static s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, return 0; } +/** + * ixgbe_atr_get_vm_pool_82599 - Gets the Virtual Machine pool + * @input: input stream to modify + * @vm_pool: the Virtual Machine pool to load + **/ +s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, + u8 *vm_pool) +{ + *vm_pool = input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET]; + + return 0; +} + /** * ixgbe_atr_get_l4type_82599 - Gets the layer 4 packet type * @input: input stream to modify diff --git a/trunk/drivers/net/ixgbe/ixgbe_common.c b/trunk/drivers/net/ixgbe/ixgbe_common.c index e3eca1316389..9595b1bfb8dd 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_common.c +++ b/trunk/drivers/net/ixgbe/ixgbe_common.c @@ -52,7 +52,6 @@ static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index); static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num); -static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); /** * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx @@ -638,7 +637,7 @@ s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) * Polls the status bit (bit 1) of the EERD or EEWR to determine when the * read or write is done respectively. **/ -static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) +s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) { u32 i; u32 reg; @@ -2450,7 +2449,7 @@ s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) * return the VLVF index where this VLAN id should be placed * **/ -static s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan) +s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan) { u32 bits = 0; u32 first_empty_slot = 0; @@ -2705,3 +2704,48 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, return 0; } + +/** + * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from + * the EEPROM + * @hw: pointer to hardware structure + * @wwnn_prefix: the alternative WWNN prefix + * @wwpn_prefix: the alternative WWPN prefix + * + * This function will read the EEPROM from the alternative SAN MAC address + * block to check the support for the alternative WWNN/WWPN prefix support. + **/ +s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix) +{ + u16 offset, caps; + u16 alt_san_mac_blk_offset; + + /* clear output first */ + *wwnn_prefix = 0xFFFF; + *wwpn_prefix = 0xFFFF; + + /* check if alternative SAN MAC is supported */ + hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR, + &alt_san_mac_blk_offset); + + if ((alt_san_mac_blk_offset == 0) || + (alt_san_mac_blk_offset == 0xFFFF)) + goto wwn_prefix_out; + + /* check capability in alternative san mac address block */ + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; + hw->eeprom.ops.read(hw, offset, &caps); + if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) + goto wwn_prefix_out; + + /* get the corresponding prefix for WWNN/WWPN */ + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; + hw->eeprom.ops.read(hw, offset, wwnn_prefix); + + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; + hw->eeprom.ops.read(hw, offset, wwpn_prefix); + +wwn_prefix_out: + return 0; +} diff --git a/trunk/drivers/net/ixgbe/ixgbe_common.h b/trunk/drivers/net/ixgbe/ixgbe_common.h index 424c223437dc..5cf15aa11cac 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_common.h +++ b/trunk/drivers/net/ixgbe/ixgbe_common.h @@ -52,6 +52,7 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, u16 *checksum_val); s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw); +s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); diff --git a/trunk/drivers/net/ixgbe/ixgbe_dcb.c b/trunk/drivers/net/ixgbe/ixgbe_dcb.c index 8bb9ddb6dffe..9aea4f04bbd2 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_dcb.c +++ b/trunk/drivers/net/ixgbe/ixgbe_dcb.c @@ -33,6 +33,98 @@ #include "ixgbe_dcb_82598.h" #include "ixgbe_dcb_82599.h" +/** + * ixgbe_dcb_config - Struct containing DCB settings. + * @dcb_config: Pointer to DCB config structure + * + * This function checks DCB rules for DCB settings. + * The following rules are checked: + * 1. The sum of bandwidth percentages of all Bandwidth Groups must total 100%. + * 2. The sum of bandwidth percentages of all Traffic Classes within a Bandwidth + * Group must total 100. + * 3. A Traffic Class should not be set to both Link Strict Priority + * and Group Strict Priority. + * 4. Link strict Bandwidth Groups can only have link strict traffic classes + * with zero bandwidth. + */ +s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *dcb_config) +{ + struct tc_bw_alloc *p; + s32 ret_val = 0; + u8 i, j, bw = 0, bw_id; + u8 bw_sum[2][MAX_BW_GROUP]; + bool link_strict[2][MAX_BW_GROUP]; + + memset(bw_sum, 0, sizeof(bw_sum)); + memset(link_strict, 0, sizeof(link_strict)); + + /* First Tx, then Rx */ + for (i = 0; i < 2; i++) { + /* Check each traffic class for rule violation */ + for (j = 0; j < MAX_TRAFFIC_CLASS; j++) { + p = &dcb_config->tc_config[j].path[i]; + + bw = p->bwg_percent; + bw_id = p->bwg_id; + + if (bw_id >= MAX_BW_GROUP) { + ret_val = DCB_ERR_CONFIG; + goto err_config; + } + if (p->prio_type == prio_link) { + link_strict[i][bw_id] = true; + /* Link strict should have zero bandwidth */ + if (bw) { + ret_val = DCB_ERR_LS_BW_NONZERO; + goto err_config; + } + } else if (!bw) { + /* + * Traffic classes without link strict + * should have non-zero bandwidth. + */ + ret_val = DCB_ERR_TC_BW_ZERO; + goto err_config; + } + bw_sum[i][bw_id] += bw; + } + + bw = 0; + + /* Check each bandwidth group for rule violation */ + for (j = 0; j < MAX_BW_GROUP; j++) { + bw += dcb_config->bw_percentage[i][j]; + /* + * Sum of bandwidth percentages of all traffic classes + * within a Bandwidth Group must total 100 except for + * link strict group (zero bandwidth). + */ + if (link_strict[i][j]) { + if (bw_sum[i][j]) { + /* + * Link strict group should have zero + * bandwidth. + */ + ret_val = DCB_ERR_LS_BWG_NONZERO; + goto err_config; + } + } else if (bw_sum[i][j] != BW_PERCENT && + bw_sum[i][j] != 0) { + ret_val = DCB_ERR_TC_BW; + goto err_config; + } + } + + if (bw != BW_PERCENT) { + ret_val = DCB_ERR_BW_GROUP; + goto err_config; + } + } + +err_config: + return ret_val; +} + /** * ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits * @ixgbe_dcb_config: Struct containing DCB settings. @@ -110,6 +202,133 @@ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *dcb_config, return ret_val; } +/** + * ixgbe_dcb_get_tc_stats - Returns status of each traffic class + * @hw: pointer to hardware structure + * @stats: pointer to statistics structure + * @tc_count: Number of elements in bwg_array. + * + * This function returns the status data for each of the Traffic Classes in use. + */ +s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats, + u8 tc_count) +{ + s32 ret = 0; + if (hw->mac.type == ixgbe_mac_82598EB) + ret = ixgbe_dcb_get_tc_stats_82598(hw, stats, tc_count); + else if (hw->mac.type == ixgbe_mac_82599EB) + ret = ixgbe_dcb_get_tc_stats_82599(hw, stats, tc_count); + return ret; +} + +/** + * ixgbe_dcb_get_pfc_stats - Returns CBFC status of each traffic class + * hw - pointer to hardware structure + * stats - pointer to statistics structure + * tc_count - Number of elements in bwg_array. + * + * This function returns the CBFC status data for each of the Traffic Classes. + */ +s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats, + u8 tc_count) +{ + s32 ret = 0; + if (hw->mac.type == ixgbe_mac_82598EB) + ret = ixgbe_dcb_get_pfc_stats_82598(hw, stats, tc_count); + else if (hw->mac.type == ixgbe_mac_82599EB) + ret = ixgbe_dcb_get_pfc_stats_82599(hw, stats, tc_count); + return ret; +} + +/** + * ixgbe_dcb_config_rx_arbiter - Config Rx arbiter + * @hw: pointer to hardware structure + * @dcb_config: pointer to ixgbe_dcb_config structure + * + * Configure Rx Data Arbiter and credits for each traffic class. + */ +s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *hw, + struct ixgbe_dcb_config *dcb_config) +{ + s32 ret = 0; + if (hw->mac.type == ixgbe_mac_82598EB) + ret = ixgbe_dcb_config_rx_arbiter_82598(hw, dcb_config); + else if (hw->mac.type == ixgbe_mac_82599EB) + ret = ixgbe_dcb_config_rx_arbiter_82599(hw, dcb_config); + return ret; +} + +/** + * ixgbe_dcb_config_tx_desc_arbiter - Config Tx Desc arbiter + * @hw: pointer to hardware structure + * @dcb_config: pointer to ixgbe_dcb_config structure + * + * Configure Tx Descriptor Arbiter and credits for each traffic class. + */ +s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *hw, + struct ixgbe_dcb_config *dcb_config) +{ + s32 ret = 0; + if (hw->mac.type == ixgbe_mac_82598EB) + ret = ixgbe_dcb_config_tx_desc_arbiter_82598(hw, dcb_config); + else if (hw->mac.type == ixgbe_mac_82599EB) + ret = ixgbe_dcb_config_tx_desc_arbiter_82599(hw, dcb_config); + return ret; +} + +/** + * ixgbe_dcb_config_tx_data_arbiter - Config Tx data arbiter + * @hw: pointer to hardware structure + * @dcb_config: pointer to ixgbe_dcb_config structure + * + * Configure Tx Data Arbiter and credits for each traffic class. + */ +s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *hw, + struct ixgbe_dcb_config *dcb_config) +{ + s32 ret = 0; + if (hw->mac.type == ixgbe_mac_82598EB) + ret = ixgbe_dcb_config_tx_data_arbiter_82598(hw, dcb_config); + else if (hw->mac.type == ixgbe_mac_82599EB) + ret = ixgbe_dcb_config_tx_data_arbiter_82599(hw, dcb_config); + return ret; +} + +/** + * ixgbe_dcb_config_pfc - Config priority flow control + * @hw: pointer to hardware structure + * @dcb_config: pointer to ixgbe_dcb_config structure + * + * Configure Priority Flow Control for each traffic class. + */ +s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *hw, + struct ixgbe_dcb_config *dcb_config) +{ + s32 ret = 0; + if (hw->mac.type == ixgbe_mac_82598EB) + ret = ixgbe_dcb_config_pfc_82598(hw, dcb_config); + else if (hw->mac.type == ixgbe_mac_82599EB) + ret = ixgbe_dcb_config_pfc_82599(hw, dcb_config); + return ret; +} + +/** + * ixgbe_dcb_config_tc_stats - Config traffic class statistics + * @hw: pointer to hardware structure + * + * Configure queue statistics registers, all queues belonging to same traffic + * class uses a single set of queue statistics counters. + */ +s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *hw) +{ + s32 ret = 0; + if (hw->mac.type == ixgbe_mac_82598EB) + ret = ixgbe_dcb_config_tc_stats_82598(hw); + else if (hw->mac.type == ixgbe_mac_82599EB) + ret = ixgbe_dcb_config_tc_stats_82599(hw); + return ret; +} + /** * ixgbe_dcb_hw_config - Config and enable DCB * @hw: pointer to hardware structure diff --git a/trunk/drivers/net/ixgbe/ixgbe_dcb.h b/trunk/drivers/net/ixgbe/ixgbe_dcb.h index eb1059f09da0..5caafd4afbc3 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_dcb.h +++ b/trunk/drivers/net/ixgbe/ixgbe_dcb.h @@ -149,9 +149,27 @@ struct ixgbe_dcb_config { /* DCB driver APIs */ +/* DCB rule checking function.*/ +s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *config); + /* DCB credits calculation */ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *, u8); +/* DCB PFC functions */ +s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *, struct ixgbe_dcb_config *g); +s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); + +/* DCB traffic class stats */ +s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *); +s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); + +/* DCB config arbiters */ +s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *, + struct ixgbe_dcb_config *); +s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *, + struct ixgbe_dcb_config *); +s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *, struct ixgbe_dcb_config *); + /* DCB hw initialization */ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *); diff --git a/trunk/drivers/net/ixgbe/ixgbe_dcb_82598.c b/trunk/drivers/net/ixgbe/ixgbe_dcb_82598.c index 50288bcadc59..f0e9279d4669 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_dcb_82598.c +++ b/trunk/drivers/net/ixgbe/ixgbe_dcb_82598.c @@ -31,6 +31,65 @@ #include "ixgbe_dcb.h" #include "ixgbe_dcb_82598.h" +/** + * ixgbe_dcb_get_tc_stats_82598 - Return status data for each traffic class + * @hw: pointer to hardware structure + * @stats: pointer to statistics structure + * @tc_count: Number of elements in bwg_array. + * + * This function returns the status data for each of the Traffic Classes in use. + */ +s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *hw, + struct ixgbe_hw_stats *stats, + u8 tc_count) +{ + int tc; + + if (tc_count > MAX_TRAFFIC_CLASS) + return DCB_ERR_PARAM; + + /* Statistics pertaining to each traffic class */ + for (tc = 0; tc < tc_count; tc++) { + /* Transmitted Packets */ + stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc)); + /* Transmitted Bytes */ + stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc)); + /* Received Packets */ + stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc)); + /* Received Bytes */ + stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc)); + } + + return 0; +} + +/** + * ixgbe_dcb_get_pfc_stats_82598 - Returns CBFC status data + * @hw: pointer to hardware structure + * @stats: pointer to statistics structure + * @tc_count: Number of elements in bwg_array. + * + * This function returns the CBFC status data for each of the Traffic Classes. + */ +s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *hw, + struct ixgbe_hw_stats *stats, + u8 tc_count) +{ + int tc; + + if (tc_count > MAX_TRAFFIC_CLASS) + return DCB_ERR_PARAM; + + for (tc = 0; tc < tc_count; tc++) { + /* Priority XOFF Transmitted */ + stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc)); + /* Priority XOFF Received */ + stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(tc)); + } + + return 0; +} + /** * ixgbe_dcb_config_packet_buffers_82598 - Configure packet buffers * @hw: pointer to hardware structure @@ -78,7 +137,7 @@ static s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw, * * Configure Rx Data Arbiter and credits for each traffic class. */ -static s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw, +s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { struct tc_bw_alloc *p; @@ -135,7 +194,7 @@ static s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw, * * Configure Tx Descriptor Arbiter and credits for each traffic class. */ -static s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw, +s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { struct tc_bw_alloc *p; @@ -183,7 +242,7 @@ static s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw, * * Configure Tx Data Arbiter and credits for each traffic class. */ -static s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw, +s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { struct tc_bw_alloc *p; @@ -296,7 +355,7 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, * Configure queue statistics registers, all queues belonging to same traffic * class uses a single set of queue statistics counters. */ -static s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw) +s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw) { u32 reg = 0; u8 i = 0; diff --git a/trunk/drivers/net/ixgbe/ixgbe_dcb_82598.h b/trunk/drivers/net/ixgbe/ixgbe_dcb_82598.h index abc03ccfa088..cc728fa092e2 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_dcb_82598.h +++ b/trunk/drivers/net/ixgbe/ixgbe_dcb_82598.h @@ -72,6 +72,21 @@ /* DCB PFC functions */ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *); +s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *, + u8); + +/* DCB traffic class stats */ +s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *); +s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *, + u8); + +/* DCB config arbiters */ +s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *, + struct ixgbe_dcb_config *); +s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *, + struct ixgbe_dcb_config *); +s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *, + struct ixgbe_dcb_config *); /* DCB hw initialization */ s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *); diff --git a/trunk/drivers/net/ixgbe/ixgbe_dcb_82599.c b/trunk/drivers/net/ixgbe/ixgbe_dcb_82599.c index 67c219f86c3a..25b02fb425ac 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_dcb_82599.c +++ b/trunk/drivers/net/ixgbe/ixgbe_dcb_82599.c @@ -30,6 +30,63 @@ #include "ixgbe_dcb.h" #include "ixgbe_dcb_82599.h" +/** + * ixgbe_dcb_get_tc_stats_82599 - Returns status for each traffic class + * @hw: pointer to hardware structure + * @stats: pointer to statistics structure + * @tc_count: Number of elements in bwg_array. + * + * This function returns the status data for each of the Traffic Classes in use. + */ +s32 ixgbe_dcb_get_tc_stats_82599(struct ixgbe_hw *hw, + struct ixgbe_hw_stats *stats, + u8 tc_count) +{ + int tc; + + if (tc_count > MAX_TRAFFIC_CLASS) + return DCB_ERR_PARAM; + /* Statistics pertaining to each traffic class */ + for (tc = 0; tc < tc_count; tc++) { + /* Transmitted Packets */ + stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc)); + /* Transmitted Bytes */ + stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc)); + /* Received Packets */ + stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc)); + /* Received Bytes */ + stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc)); + } + + return 0; +} + +/** + * ixgbe_dcb_get_pfc_stats_82599 - Return CBFC status data + * @hw: pointer to hardware structure + * @stats: pointer to statistics structure + * @tc_count: Number of elements in bwg_array. + * + * This function returns the CBFC status data for each of the Traffic Classes. + */ +s32 ixgbe_dcb_get_pfc_stats_82599(struct ixgbe_hw *hw, + struct ixgbe_hw_stats *stats, + u8 tc_count) +{ + int tc; + + if (tc_count > MAX_TRAFFIC_CLASS) + return DCB_ERR_PARAM; + for (tc = 0; tc < tc_count; tc++) { + /* Priority XOFF Transmitted */ + stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc)); + /* Priority XOFF Received */ + stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(tc)); + } + + return 0; +} + /** * ixgbe_dcb_config_packet_buffers_82599 - Configure DCB packet buffers * @hw: pointer to hardware structure @@ -37,7 +94,7 @@ * * Configure packet buffers for DCB mode. */ -static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw, +s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { s32 ret_val = 0; @@ -79,7 +136,7 @@ static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw, * * Configure Rx Packet Arbiter and credits for each traffic class. */ -static s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw, +s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { struct tc_bw_alloc *p; @@ -134,7 +191,7 @@ static s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw, * * Configure Tx Descriptor Arbiter and credits for each traffic class. */ -static s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw, +s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { struct tc_bw_alloc *p; @@ -181,7 +238,7 @@ static s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw, * * Configure Tx Packet Arbiter and credits for each traffic class. */ -static s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw, +s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { struct tc_bw_alloc *p; @@ -302,7 +359,7 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, * Configure queue statistics registers, all queues belonging to same traffic * class uses a single set of queue statistics counters. */ -static s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw) +s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw) { u32 reg = 0; u8 i = 0; @@ -355,7 +412,7 @@ static s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw) * * Configure general DCB parameters. */ -static s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw) +s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw) { u32 reg; u32 q; diff --git a/trunk/drivers/net/ixgbe/ixgbe_dcb_82599.h b/trunk/drivers/net/ixgbe/ixgbe_dcb_82599.h index 18d7fbf6c292..0f3f791e1e1d 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_dcb_82599.h +++ b/trunk/drivers/net/ixgbe/ixgbe_dcb_82599.h @@ -101,6 +101,24 @@ /* DCB PFC functions */ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config); +s32 ixgbe_dcb_get_pfc_stats_82599(struct ixgbe_hw *hw, + struct ixgbe_hw_stats *stats, + u8 tc_count); + +/* DCB traffic class stats */ +s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw); +s32 ixgbe_dcb_get_tc_stats_82599(struct ixgbe_hw *hw, + struct ixgbe_hw_stats *stats, + u8 tc_count); + +/* DCB config arbiters */ +s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw, + struct ixgbe_dcb_config *dcb_config); +s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw, + struct ixgbe_dcb_config *dcb_config); +s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw, + struct ixgbe_dcb_config *dcb_config); + /* DCB hw initialization */ s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw, diff --git a/trunk/drivers/net/ixgbe/ixgbe_main.c b/trunk/drivers/net/ixgbe/ixgbe_main.c index 790a0dae1247..95dbf60c8169 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ixgbe/ixgbe_main.c @@ -3374,6 +3374,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) if (hw->mac.type == ixgbe_mac_82598EB) netif_set_gso_max_size(adapter->netdev, 32768); + ixgbe_dcb_check_config(&adapter->dcb_cfg); ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_TX_CONFIG); ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_RX_CONFIG); diff --git a/trunk/drivers/net/ixgbe/ixgbe_mbx.c b/trunk/drivers/net/ixgbe/ixgbe_mbx.c index 435e0281e1f8..d75f9148eb1f 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_mbx.c +++ b/trunk/drivers/net/ixgbe/ixgbe_mbx.c @@ -200,8 +200,7 @@ static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id) * returns SUCCESS if it successfully received a message notification and * copied it into the receive buffer. **/ -static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, - u16 mbx_id) +s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; s32 ret_val = IXGBE_ERR_MBX; @@ -228,7 +227,7 @@ static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, * returns SUCCESS if it successfully copied message into the buffer and * received an ack to that message within delay * timeout period **/ -static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, +s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; @@ -248,6 +247,20 @@ static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, return ret_val; } +/** + * ixgbe_init_mbx_ops_generic - Initialize MB function pointers + * @hw: pointer to the HW structure + * + * Setup the mailbox read and write message function pointers + **/ +void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + + mbx->ops.read_posted = ixgbe_read_posted_mbx; + mbx->ops.write_posted = ixgbe_write_posted_mbx; +} + static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index) { u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index)); diff --git a/trunk/drivers/net/ixgbe/ixgbe_mbx.h b/trunk/drivers/net/ixgbe/ixgbe_mbx.h index c5ae4b4da83a..be7ab3309ab7 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_mbx.h +++ b/trunk/drivers/net/ixgbe/ixgbe_mbx.h @@ -83,9 +83,12 @@ s32 ixgbe_read_mbx(struct ixgbe_hw *, u32 *, u16, u16); s32 ixgbe_write_mbx(struct ixgbe_hw *, u32 *, u16, u16); +s32 ixgbe_read_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16); +s32 ixgbe_write_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16); s32 ixgbe_check_for_msg(struct ixgbe_hw *, u16); s32 ixgbe_check_for_ack(struct ixgbe_hw *, u16); s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16); +void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw); void ixgbe_init_mbx_params_pf(struct ixgbe_hw *); extern struct ixgbe_mbx_operations mbx_ops_82599; diff --git a/trunk/drivers/net/ixgbe/ixgbe_sriov.c b/trunk/drivers/net/ixgbe/ixgbe_sriov.c index a6b720ae7fea..49661a138e22 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_sriov.c +++ b/trunk/drivers/net/ixgbe/ixgbe_sriov.c @@ -43,8 +43,8 @@ #include "ixgbe_sriov.h" -static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, - int entries, u16 *hash_list, u32 vf) +int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, + int entries, u16 *hash_list, u32 vf) { struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; struct ixgbe_hw *hw = &adapter->hw; @@ -104,14 +104,13 @@ void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter) } } -static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, - u32 vf) +int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf) { return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add); } -static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe) +void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe) { u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf)); vmolr |= (IXGBE_VMOLR_ROMPE | @@ -135,7 +134,7 @@ static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, u32 vid, u32 vf) IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0); } -static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) +inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) { struct ixgbe_hw *hw = &adapter->hw; int rar_entry = hw->mac.num_rar_entries - (vf + 1); @@ -163,8 +162,8 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) hw->mac.ops.clear_rar(hw, rar_entry); } -static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, - int vf, unsigned char *mac_addr) +int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, + int vf, unsigned char *mac_addr) { struct ixgbe_hw *hw = &adapter->hw; int rar_entry = hw->mac.num_rar_entries - (vf + 1); @@ -198,7 +197,7 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) return 0; } -static inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) +inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) { struct ixgbe_hw *hw = &adapter->hw; u32 reg; diff --git a/trunk/drivers/net/ixgbe/ixgbe_sriov.h b/trunk/drivers/net/ixgbe/ixgbe_sriov.h index 9a424bb688c0..184730ecdfb6 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_sriov.h +++ b/trunk/drivers/net/ixgbe/ixgbe_sriov.h @@ -28,8 +28,16 @@ #ifndef _IXGBE_SRIOV_H_ #define _IXGBE_SRIOV_H_ +int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, + int entries, u16 *hash_list, u32 vf); void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter); +int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf); +void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe); +void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf); +void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf); void ixgbe_msg_task(struct ixgbe_adapter *adapter); +int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, + int vf, unsigned char *mac_addr); int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask); void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter); void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter); diff --git a/trunk/drivers/net/netconsole.c b/trunk/drivers/net/netconsole.c index 94255f09093d..ca142c47b2e4 100644 --- a/trunk/drivers/net/netconsole.c +++ b/trunk/drivers/net/netconsole.c @@ -678,14 +678,7 @@ static int netconsole_netdev_event(struct notifier_block *this, strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ); break; case NETDEV_UNREGISTER: - /* - * rtnl_lock already held - */ - if (nt->np.dev) { - __netpoll_cleanup(&nt->np); - dev_put(nt->np.dev); - nt->np.dev = NULL; - } + netpoll_cleanup(&nt->np); /* Fall through */ case NETDEV_GOING_DOWN: case NETDEV_BONDING_DESLAVE: diff --git a/trunk/drivers/net/netxen/netxen_nic.h b/trunk/drivers/net/netxen/netxen_nic.h index 92f89af0720e..6dca3574e355 100644 --- a/trunk/drivers/net/netxen/netxen_nic.h +++ b/trunk/drivers/net/netxen/netxen_nic.h @@ -175,10 +175,7 @@ #define MAX_NUM_CARDS 4 #define MAX_BUFFERS_PER_CMD 32 -#define MAX_TSO_HEADER_DESC 2 -#define MGMT_CMD_DESC_RESV 4 -#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \ - + MGMT_CMD_DESC_RESV) +#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + 4) #define NX_MAX_TX_TIMEOUTS 2 /* diff --git a/trunk/drivers/net/netxen/netxen_nic_hw.c b/trunk/drivers/net/netxen/netxen_nic_hw.c index 4b4ac7106786..29d7b93d0493 100644 --- a/trunk/drivers/net/netxen/netxen_nic_hw.c +++ b/trunk/drivers/net/netxen/netxen_nic_hw.c @@ -598,14 +598,8 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, if (nr_desc >= netxen_tx_avail(tx_ring)) { netif_tx_stop_queue(tx_ring->txq); - smp_mb(); - if (netxen_tx_avail(tx_ring) > nr_desc) { - if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) - netif_tx_wake_queue(tx_ring->txq); - } else { - __netif_tx_unlock_bh(tx_ring->txq); - return -EBUSY; - } + __netif_tx_unlock_bh(tx_ring->txq); + return -EBUSY; } do { @@ -1822,14 +1816,14 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) if (netxen_rom_fast_read(adapter, offset, &board_type)) return -EIO; + adapter->ahw.board_type = board_type; + if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) { u32 gpio = NXRD32(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I); if ((gpio & 0x8000) == 0) board_type = NETXEN_BRDTYPE_P3_10G_TP; } - adapter->ahw.board_type = board_type; - switch (board_type) { case NETXEN_BRDTYPE_P2_SB35_4G: adapter->ahw.port_type = NETXEN_NIC_GBE; diff --git a/trunk/drivers/net/netxen/netxen_nic_init.c b/trunk/drivers/net/netxen/netxen_nic_init.c index 95fe552aa279..a2d805aa75cd 100644 --- a/trunk/drivers/net/netxen/netxen_nic_init.c +++ b/trunk/drivers/net/netxen/netxen_nic_init.c @@ -1763,10 +1763,14 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) smp_mb(); - if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) - if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) + if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { + __netif_tx_lock(tx_ring->txq, smp_processor_id()); + if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) { netif_wake_queue(netdev); - adapter->tx_timeo_cnt = 0; + adapter->tx_timeo_cnt = 0; + } + __netif_tx_unlock(tx_ring->txq); + } } /* * If everything is freed up to consumer then check if the ring is full diff --git a/trunk/drivers/net/netxen/netxen_nic_main.c b/trunk/drivers/net/netxen/netxen_nic_main.c index 6f111691aca4..2c6ceeb592b3 100644 --- a/trunk/drivers/net/netxen/netxen_nic_main.c +++ b/trunk/drivers/net/netxen/netxen_nic_main.c @@ -125,6 +125,11 @@ netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, struct nx_host_tx_ring *tx_ring) { NXWRIO(adapter, tx_ring->crb_cmd_producer, tx_ring->producer); + + if (netxen_tx_avail(tx_ring) <= TX_STOP_THRESH) { + netif_stop_queue(adapter->netdev); + smp_mb(); + } } static uint32_t crb_cmd_consumer[4] = { @@ -1204,7 +1209,7 @@ netxen_setup_netdev(struct netxen_adapter *adapter, adapter->max_mc_count = 16; netdev->netdev_ops = &netxen_netdev_ops; - netdev->watchdog_timeo = 5*HZ; + netdev->watchdog_timeo = 2*HZ; netxen_nic_change_mtu(netdev, netdev->mtu); @@ -1249,28 +1254,6 @@ netxen_setup_netdev(struct netxen_adapter *adapter, return 0; } -#ifdef CONFIG_PCIEAER -static void netxen_mask_aer_correctable(struct netxen_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - struct pci_dev *root = pdev->bus->self; - u32 aer_pos; - - if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM && - adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP) - return; - - if (root->pcie_type != PCI_EXP_TYPE_ROOT_PORT) - return; - - aer_pos = pci_find_ext_capability(root, PCI_EXT_CAP_ID_ERR); - if (!aer_pos) - return; - - pci_write_config_dword(root, aer_pos + PCI_ERR_COR_MASK, 0xffff); -} -#endif - static int __devinit netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -1339,10 +1322,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_iounmap; } -#ifdef CONFIG_PCIEAER - netxen_mask_aer_correctable(adapter); -#endif - /* Mezz cards have PCI function 0,2,3 enabled */ switch (adapter->ahw.board_type) { case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: @@ -1846,13 +1825,9 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* 4 fragments per cmd des */ no_of_desc = (frag_count + 3) >> 2; - if (unlikely(netxen_tx_avail(tx_ring) <= TX_STOP_THRESH)) { + if (unlikely(no_of_desc + 2 > netxen_tx_avail(tx_ring))) { netif_stop_queue(netdev); - smp_mb(); - if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) - netif_start_queue(netdev); - else - return NETDEV_TX_BUSY; + return NETDEV_TX_BUSY; } producer = tx_ring->producer; diff --git a/trunk/drivers/net/niu.c b/trunk/drivers/net/niu.c index 781e368329f9..c0437fd8d3f2 100644 --- a/trunk/drivers/net/niu.c +++ b/trunk/drivers/net/niu.c @@ -7090,20 +7090,24 @@ static int niu_get_hash_opts(struct niu *np, struct ethtool_rxnfc *nfc) static void niu_get_ip4fs_from_tcam_key(struct niu_tcam_entry *tp, struct ethtool_rx_flow_spec *fsp) { - u32 tmp; - u16 prt; - tmp = (tp->key[3] & TCAM_V4KEY3_SADDR) >> TCAM_V4KEY3_SADDR_SHIFT; - fsp->h_u.tcp_ip4_spec.ip4src = cpu_to_be32(tmp); - - tmp = (tp->key[3] & TCAM_V4KEY3_DADDR) >> TCAM_V4KEY3_DADDR_SHIFT; - fsp->h_u.tcp_ip4_spec.ip4dst = cpu_to_be32(tmp); - - tmp = (tp->key_mask[3] & TCAM_V4KEY3_SADDR) >> TCAM_V4KEY3_SADDR_SHIFT; - fsp->m_u.tcp_ip4_spec.ip4src = cpu_to_be32(tmp); - - tmp = (tp->key_mask[3] & TCAM_V4KEY3_DADDR) >> TCAM_V4KEY3_DADDR_SHIFT; - fsp->m_u.tcp_ip4_spec.ip4dst = cpu_to_be32(tmp); + fsp->h_u.tcp_ip4_spec.ip4src = (tp->key[3] & TCAM_V4KEY3_SADDR) >> + TCAM_V4KEY3_SADDR_SHIFT; + fsp->h_u.tcp_ip4_spec.ip4dst = (tp->key[3] & TCAM_V4KEY3_DADDR) >> + TCAM_V4KEY3_DADDR_SHIFT; + fsp->m_u.tcp_ip4_spec.ip4src = (tp->key_mask[3] & TCAM_V4KEY3_SADDR) >> + TCAM_V4KEY3_SADDR_SHIFT; + fsp->m_u.tcp_ip4_spec.ip4dst = (tp->key_mask[3] & TCAM_V4KEY3_DADDR) >> + TCAM_V4KEY3_DADDR_SHIFT; + + fsp->h_u.tcp_ip4_spec.ip4src = + cpu_to_be32(fsp->h_u.tcp_ip4_spec.ip4src); + fsp->m_u.tcp_ip4_spec.ip4src = + cpu_to_be32(fsp->m_u.tcp_ip4_spec.ip4src); + fsp->h_u.tcp_ip4_spec.ip4dst = + cpu_to_be32(fsp->h_u.tcp_ip4_spec.ip4dst); + fsp->m_u.tcp_ip4_spec.ip4dst = + cpu_to_be32(fsp->m_u.tcp_ip4_spec.ip4dst); fsp->h_u.tcp_ip4_spec.tos = (tp->key[2] & TCAM_V4KEY2_TOS) >> TCAM_V4KEY2_TOS_SHIFT; @@ -7114,40 +7118,54 @@ static void niu_get_ip4fs_from_tcam_key(struct niu_tcam_entry *tp, case TCP_V4_FLOW: case UDP_V4_FLOW: case SCTP_V4_FLOW: - prt = ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >> - TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16; - fsp->h_u.tcp_ip4_spec.psrc = cpu_to_be16(prt); - - prt = ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >> - TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff; - fsp->h_u.tcp_ip4_spec.pdst = cpu_to_be16(prt); - - prt = ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >> - TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16; - fsp->m_u.tcp_ip4_spec.psrc = cpu_to_be16(prt); - - prt = ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >> + fsp->h_u.tcp_ip4_spec.psrc = + ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >> + TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16; + fsp->h_u.tcp_ip4_spec.pdst = + ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >> TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff; - fsp->m_u.tcp_ip4_spec.pdst = cpu_to_be16(prt); + fsp->m_u.tcp_ip4_spec.psrc = + ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >> + TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16; + fsp->m_u.tcp_ip4_spec.pdst = + ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >> + TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff; + + fsp->h_u.tcp_ip4_spec.psrc = + cpu_to_be16(fsp->h_u.tcp_ip4_spec.psrc); + fsp->h_u.tcp_ip4_spec.pdst = + cpu_to_be16(fsp->h_u.tcp_ip4_spec.pdst); + fsp->m_u.tcp_ip4_spec.psrc = + cpu_to_be16(fsp->m_u.tcp_ip4_spec.psrc); + fsp->m_u.tcp_ip4_spec.pdst = + cpu_to_be16(fsp->m_u.tcp_ip4_spec.pdst); break; case AH_V4_FLOW: case ESP_V4_FLOW: - tmp = (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >> + fsp->h_u.ah_ip4_spec.spi = + (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >> TCAM_V4KEY2_PORT_SPI_SHIFT; - fsp->h_u.ah_ip4_spec.spi = cpu_to_be32(tmp); - - tmp = (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >> + fsp->m_u.ah_ip4_spec.spi = + (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >> TCAM_V4KEY2_PORT_SPI_SHIFT; - fsp->m_u.ah_ip4_spec.spi = cpu_to_be32(tmp); + + fsp->h_u.ah_ip4_spec.spi = + cpu_to_be32(fsp->h_u.ah_ip4_spec.spi); + fsp->m_u.ah_ip4_spec.spi = + cpu_to_be32(fsp->m_u.ah_ip4_spec.spi); break; case IP_USER_FLOW: - tmp = (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >> + fsp->h_u.usr_ip4_spec.l4_4_bytes = + (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >> TCAM_V4KEY2_PORT_SPI_SHIFT; - fsp->h_u.usr_ip4_spec.l4_4_bytes = cpu_to_be32(tmp); - - tmp = (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >> + fsp->m_u.usr_ip4_spec.l4_4_bytes = + (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >> TCAM_V4KEY2_PORT_SPI_SHIFT; - fsp->m_u.usr_ip4_spec.l4_4_bytes = cpu_to_be32(tmp); + + fsp->h_u.usr_ip4_spec.l4_4_bytes = + cpu_to_be32(fsp->h_u.usr_ip4_spec.l4_4_bytes); + fsp->m_u.usr_ip4_spec.l4_4_bytes = + cpu_to_be32(fsp->m_u.usr_ip4_spec.l4_4_bytes); fsp->h_u.usr_ip4_spec.proto = (tp->key[2] & TCAM_V4KEY2_PROTO) >> diff --git a/trunk/drivers/net/ns83820.c b/trunk/drivers/net/ns83820.c index 84134c766f3a..3bbd0aab17e8 100644 --- a/trunk/drivers/net/ns83820.c +++ b/trunk/drivers/net/ns83820.c @@ -772,7 +772,7 @@ static int ns83820_setup_rx(struct net_device *ndev) phy_intr(ndev); /* Okay, let it rip */ - spin_lock(&dev->misc_lock); + spin_lock_irq(&dev->misc_lock); dev->IMR_cache |= ISR_PHY; dev->IMR_cache |= ISR_RXRCMP; //dev->IMR_cache |= ISR_RXERR; diff --git a/trunk/drivers/net/pch_gbe/pch_gbe_ethtool.c b/trunk/drivers/net/pch_gbe/pch_gbe_ethtool.c index c8cc32c0edc9..e06c6aea4527 100644 --- a/trunk/drivers/net/pch_gbe/pch_gbe_ethtool.c +++ b/trunk/drivers/net/pch_gbe/pch_gbe_ethtool.c @@ -113,10 +113,9 @@ static int pch_gbe_set_settings(struct net_device *netdev, pch_gbe_hal_write_phy_reg(hw, MII_BMCR, BMCR_RESET); - if (ecmd->speed == USHRT_MAX) { + if (ecmd->speed == -1) ecmd->speed = SPEED_1000; ecmd->duplex = DUPLEX_FULL; - } ret = mii_ethtool_sset(&adapter->mii, ecmd); if (ret) { pr_err("Error: mii_ethtool_sset\n"); diff --git a/trunk/drivers/net/pch_gbe/pch_gbe_main.c b/trunk/drivers/net/pch_gbe/pch_gbe_main.c index cf4b49d6c6da..e44644f169fd 100644 --- a/trunk/drivers/net/pch_gbe/pch_gbe_main.c +++ b/trunk/drivers/net/pch_gbe/pch_gbe_main.c @@ -2394,7 +2394,7 @@ static int pch_gbe_probe(struct pci_dev *pdev, return ret; } -static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = { +static const struct pci_device_id pch_gbe_pcidev_id[] = { {.vendor = PCI_VENDOR_ID_INTEL, .device = PCI_DEVICE_ID_INTEL_IOH1_GBE, .subvendor = PCI_ANY_ID, diff --git a/trunk/drivers/net/qlcnic/qlcnic_ethtool.c b/trunk/drivers/net/qlcnic/qlcnic_ethtool.c index 25e93a53fca0..2568aa665024 100644 --- a/trunk/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/trunk/drivers/net/qlcnic/qlcnic_ethtool.c @@ -78,25 +78,7 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = { }; -static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx unicast frames", - "rx multicast frames", - "rx broadcast frames", - "rx dropped frames", - "rx errors", - "rx local frames", - "rx numbytes", - "tx unicast frames", - "tx multicast frames", - "tx broadcast frames", - "tx dropped frames", - "tx errors", - "tx local frames", - "tx numbytes", -}; - #define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) -#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats) static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = { "Register_Test_on_offline", @@ -643,13 +625,10 @@ static int qlcnic_reg_test(struct net_device *dev) static int qlcnic_get_sset_count(struct net_device *dev, int sset) { - struct qlcnic_adapter *adapter = netdev_priv(dev); switch (sset) { case ETH_SS_TEST: return QLCNIC_TEST_LEN; case ETH_SS_STATS: - if (adapter->flags & QLCNIC_ESWITCH_ENABLED) - return QLCNIC_STATS_LEN + QLCNIC_DEVICE_STATS_LEN; return QLCNIC_STATS_LEN; default: return -EOPNOTSUPP; @@ -816,8 +795,7 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, static void qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data) { - struct qlcnic_adapter *adapter = netdev_priv(dev); - int index, i; + int index; switch (stringset) { case ETH_SS_TEST: @@ -830,43 +808,16 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data) qlcnic_gstrings_stats[index].stat_string, ETH_GSTRING_LEN); } - if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) - return; - for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) { - memcpy(data + index * ETH_GSTRING_LEN, - qlcnic_device_gstrings_stats[i], - ETH_GSTRING_LEN); - } + break; } } -#define QLCNIC_FILL_ESWITCH_STATS(VAL1) \ - (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) ? 0 : VAL1) - -static void -qlcnic_fill_device_stats(int *index, u64 *data, - struct __qlcnic_esw_statistics *stats) -{ - int ind = *index; - - data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->unicast_frames); - data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->multicast_frames); - data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->broadcast_frames); - data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->dropped_frames); - data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->errors); - data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->local_frames); - data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->numbytes); - - *index = ind; -} - static void qlcnic_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 * data) { struct qlcnic_adapter *adapter = netdev_priv(dev); - struct qlcnic_esw_statistics port_stats; - int index, ret; + int index; for (index = 0; index < QLCNIC_STATS_LEN; index++) { char *p = @@ -876,24 +827,6 @@ qlcnic_get_ethtool_stats(struct net_device *dev, (qlcnic_gstrings_stats[index].sizeof_stat == sizeof(u64)) ? *(u64 *)p:(*(u32 *)p); } - - if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) - return; - - memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics)); - ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func, - QLCNIC_QUERY_RX_COUNTER, &port_stats.rx); - if (ret) - return; - - qlcnic_fill_device_stats(&index, data, &port_stats.rx); - - ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func, - QLCNIC_QUERY_TX_COUNTER, &port_stats.tx); - if (ret) - return; - - qlcnic_fill_device_stats(&index, data, &port_stats.tx); } static int qlcnic_set_tx_csum(struct net_device *dev, u32 data) diff --git a/trunk/drivers/net/r8169.c b/trunk/drivers/net/r8169.c index 1760533852a4..bc669a40ae96 100644 --- a/trunk/drivers/net/r8169.c +++ b/trunk/drivers/net/r8169.c @@ -187,7 +187,12 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); -static int rx_buf_sz = 16383; +/* + * we set our copybreak very high so that we don't have + * to allocate 16k frames all the time (see note in + * rtl8169_open() + */ +static int rx_copybreak = 16383; static int use_dac; static struct { u32 msg_enable; @@ -479,8 +484,10 @@ struct rtl8169_private { struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ dma_addr_t TxPhyAddr; dma_addr_t RxPhyAddr; - void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ + struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ + unsigned align; + unsigned rx_buf_sz; struct timer_list timer; u16 cp_cmd; u16 intr_event; @@ -508,6 +515,8 @@ struct rtl8169_private { MODULE_AUTHOR("Realtek and the Linux r8169 crew "); MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); +module_param(rx_copybreak, int, 0); +MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); module_param(use_dac, int, 0); MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); module_param_named(debug, debug.msg_enable, int, 0); @@ -3187,6 +3196,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->features |= NETIF_F_GRO; tp->intr_mask = 0xffff; + tp->align = cfg->align; tp->hw_start = cfg->hw_start; tp->intr_event = cfg->intr_event; tp->napi_event = cfg->napi_event; @@ -3256,6 +3266,18 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } +static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, + unsigned int mtu) +{ + unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; + + if (max_frame != 16383) + printk(KERN_WARNING PFX "WARNING! Changing of MTU on this " + "NIC may lead to frame reception errors!\n"); + + tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; +} + static int rtl8169_open(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -3264,6 +3286,18 @@ static int rtl8169_open(struct net_device *dev) pm_runtime_get_sync(&pdev->dev); + /* + * Note that we use a magic value here, its wierd I know + * its done because, some subset of rtl8169 hardware suffers from + * a problem in which frames received that are longer than + * the size set in RxMaxSize register return garbage sizes + * when received. To avoid this we need to turn off filtering, + * which is done by setting a value of 16383 in the RxMaxSize register + * and allocating 16k frames to handle the largest possible rx value + * thats what the magic math below does. + */ + rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN); + /* * Rx and Tx desscriptors needs 256 bytes alignment. * dma_alloc_coherent provides more. @@ -3440,7 +3474,7 @@ static void rtl_hw_start_8169(struct net_device *dev) RTL_W8(EarlyTxThres, EarlyTxThld); - rtl_set_rx_max_size(ioaddr, rx_buf_sz); + rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || (tp->mac_version == RTL_GIGA_MAC_VER_02) || @@ -3701,7 +3735,7 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_W8(EarlyTxThres, EarlyTxThld); - rtl_set_rx_max_size(ioaddr, rx_buf_sz); + rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; @@ -3881,7 +3915,7 @@ static void rtl_hw_start_8101(struct net_device *dev) RTL_W8(EarlyTxThres, EarlyTxThld); - rtl_set_rx_max_size(ioaddr, rx_buf_sz); + rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; @@ -3922,6 +3956,8 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) rtl8169_down(dev); + rtl8169_set_rxbufsize(tp, dev->mtu); + ret = rtl8169_init_ring(dev); if (ret < 0) goto out; @@ -3942,15 +3978,15 @@ static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); } -static void rtl8169_free_rx_databuff(struct rtl8169_private *tp, - void **data_buff, struct RxDesc *desc) +static void rtl8169_free_rx_skb(struct rtl8169_private *tp, + struct sk_buff **sk_buff, struct RxDesc *desc) { struct pci_dev *pdev = tp->pci_dev; - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), rx_buf_sz, + dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), tp->rx_buf_sz, PCI_DMA_FROMDEVICE); - kfree(*data_buff); - *data_buff = NULL; + dev_kfree_skb(*sk_buff); + *sk_buff = NULL; rtl8169_make_unusable_by_asic(desc); } @@ -3969,34 +4005,33 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, rtl8169_mark_to_asic(desc, rx_buf_sz); } -static inline void *rtl8169_align(void *data) -{ - return (void *)ALIGN((long)data, 16); -} - -static struct sk_buff *rtl8169_alloc_rx_data(struct pci_dev *pdev, +static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev, - struct RxDesc *desc) + struct RxDesc *desc, int rx_buf_sz, + unsigned int align, gfp_t gfp) { - void *data; + struct sk_buff *skb; dma_addr_t mapping; - int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1; + unsigned int pad; - data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node); - if (!data) - return NULL; + pad = align ? align : NET_IP_ALIGN; - if (rtl8169_align(data) != data) { - kfree(data); - data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node); - if (!data) - return NULL; - } - mapping = dma_map_single(&pdev->dev, rtl8169_align(data), rx_buf_sz, + skb = __netdev_alloc_skb(dev, rx_buf_sz + pad, gfp); + if (!skb) + goto err_out; + + skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); + + mapping = dma_map_single(&pdev->dev, skb->data, rx_buf_sz, PCI_DMA_FROMDEVICE); rtl8169_map_to_asic(desc, mapping, rx_buf_sz); - return data; +out: + return skb; + +err_out: + rtl8169_make_unusable_by_asic(desc); + goto out; } static void rtl8169_rx_clear(struct rtl8169_private *tp) @@ -4004,8 +4039,8 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp) unsigned int i; for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_databuff[i]) { - rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i, + if (tp->Rx_skbuff[i]) { + rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, tp->RxDescArray + i); } } @@ -4017,21 +4052,21 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, u32 cur; for (cur = start; end - cur != 0; cur++) { - void *data; + struct sk_buff *skb; unsigned int i = cur % NUM_RX_DESC; WARN_ON((s32)(end - cur) < 0); - if (tp->Rx_databuff[i]) + if (tp->Rx_skbuff[i]) continue; - data = rtl8169_alloc_rx_data(tp->pci_dev, dev, - tp->RxDescArray + i); - if (!data) { - rtl8169_make_unusable_by_asic(tp->RxDescArray + i); + skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, + tp->RxDescArray + i, + tp->rx_buf_sz, tp->align, gfp); + if (!skb) break; - } - tp->Rx_databuff[i] = data; + + tp->Rx_skbuff[i] = skb; } return cur - start; } @@ -4053,7 +4088,7 @@ static int rtl8169_init_ring(struct net_device *dev) rtl8169_init_ring_indexes(tp); memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *)); + memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC, GFP_KERNEL) != NUM_RX_DESC) goto err_out; @@ -4438,23 +4473,27 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1) skb_checksum_none_assert(skb); } -static struct sk_buff *rtl8169_try_rx_copy(void *data, - struct rtl8169_private *tp, - int pkt_size, - dma_addr_t addr) +static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, + struct rtl8169_private *tp, int pkt_size, + dma_addr_t addr) { struct sk_buff *skb; + bool done = false; + + if (pkt_size >= rx_copybreak) + goto out; + + skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); + if (!skb) + goto out; - data = rtl8169_align(data); dma_sync_single_for_cpu(&tp->pci_dev->dev, addr, pkt_size, PCI_DMA_FROMDEVICE); - prefetch(data); - skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); - if (skb) - memcpy(skb->data, data, pkt_size); - dma_sync_single_for_device(&tp->pci_dev->dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - return skb; + skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); + *sk_buff = skb; + done = true; +out: + return done; } /* @@ -4469,7 +4508,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, void __iomem *ioaddr, u32 budget) { unsigned int cur_rx, rx_left; - unsigned int count; + unsigned int delta, count; int polling = (budget != ~(u32)0) ? 1 : 0; cur_rx = tp->cur_rx; @@ -4498,11 +4537,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev, rtl8169_schedule_work(dev, rtl8169_reset_task); dev->stats.rx_fifo_errors++; } - rtl8169_mark_to_asic(desc, rx_buf_sz); + rtl8169_mark_to_asic(desc, tp->rx_buf_sz); } else { - struct sk_buff *skb; + struct sk_buff *skb = tp->Rx_skbuff[entry]; dma_addr_t addr = le64_to_cpu(desc->addr); int pkt_size = (status & 0x00001FFF) - 4; + struct pci_dev *pdev = tp->pci_dev; /* * The driver does not support incoming fragmented @@ -4512,16 +4552,18 @@ static int rtl8169_rx_interrupt(struct net_device *dev, if (unlikely(rtl8169_fragmented_frame(status))) { dev->stats.rx_dropped++; dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, rx_buf_sz); + rtl8169_mark_to_asic(desc, tp->rx_buf_sz); continue; } - skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], - tp, pkt_size, addr); - rtl8169_mark_to_asic(desc, rx_buf_sz); - if (!skb) { - dev->stats.rx_dropped++; - continue; + if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { + dma_sync_single_for_device(&pdev->dev, addr, + pkt_size, PCI_DMA_FROMDEVICE); + rtl8169_mark_to_asic(desc, tp->rx_buf_sz); + } else { + dma_unmap_single(&pdev->dev, addr, tp->rx_buf_sz, + PCI_DMA_FROMDEVICE); + tp->Rx_skbuff[entry] = NULL; } rtl8169_rx_csum(skb, status); @@ -4550,7 +4592,20 @@ static int rtl8169_rx_interrupt(struct net_device *dev, count = cur_rx - tp->cur_rx; tp->cur_rx = cur_rx; - tp->dirty_rx += count; + delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, GFP_ATOMIC); + if (!delta && count) + netif_info(tp, intr, dev, "no Rx buffer allocated\n"); + tp->dirty_rx += delta; + + /* + * FIXME: until there is periodic timer to try and refill the ring, + * a temporary shortage may definitely kill the Rx process. + * - disable the asic to try and avoid an overflow and kick it again + * after refill ? + * - how do others driver handle this condition (Uh oh...). + */ + if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) + netif_emerg(tp, intr, dev, "Rx buffers exhausted\n"); return count; } diff --git a/trunk/drivers/net/stmmac/common.h b/trunk/drivers/net/stmmac/common.h index 375ea193e139..dec7ce40c27a 100644 --- a/trunk/drivers/net/stmmac/common.h +++ b/trunk/drivers/net/stmmac/common.h @@ -235,9 +235,9 @@ struct mii_regs { }; struct mac_device_info { - const struct stmmac_ops *mac; - const struct stmmac_desc_ops *desc; - const struct stmmac_dma_ops *dma; + struct stmmac_ops *mac; + struct stmmac_desc_ops *desc; + struct stmmac_dma_ops *dma; struct mii_regs mii; /* MII register Addresses */ struct mac_link link; }; diff --git a/trunk/drivers/net/stmmac/dwmac100.h b/trunk/drivers/net/stmmac/dwmac100.h index 7c6d857a9cc7..97956cbf1cb4 100644 --- a/trunk/drivers/net/stmmac/dwmac100.h +++ b/trunk/drivers/net/stmmac/dwmac100.h @@ -118,4 +118,4 @@ enum ttc_control { #define DMA_MISSED_FRAME_OVE_M 0x00010000 /* Missed Frame Overflow */ #define DMA_MISSED_FRAME_M_CNTR 0x0000ffff /* Missed Frame Couinter */ -extern const struct stmmac_dma_ops dwmac100_dma_ops; +extern struct stmmac_dma_ops dwmac100_dma_ops; diff --git a/trunk/drivers/net/stmmac/dwmac1000.h b/trunk/drivers/net/stmmac/dwmac1000.h index cfcef0ea0fa5..81ee4fd04386 100644 --- a/trunk/drivers/net/stmmac/dwmac1000.h +++ b/trunk/drivers/net/stmmac/dwmac1000.h @@ -205,4 +205,4 @@ enum rtc_control { #define GMAC_MMC_TX_INTR 0x108 #define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 -extern const struct stmmac_dma_ops dwmac1000_dma_ops; +extern struct stmmac_dma_ops dwmac1000_dma_ops; diff --git a/trunk/drivers/net/stmmac/dwmac1000_core.c b/trunk/drivers/net/stmmac/dwmac1000_core.c index 6ae4c3f4c63c..65667b692024 100644 --- a/trunk/drivers/net/stmmac/dwmac1000_core.c +++ b/trunk/drivers/net/stmmac/dwmac1000_core.c @@ -212,7 +212,7 @@ static void dwmac1000_irq_status(void __iomem *ioaddr) } } -static const struct stmmac_ops dwmac1000_ops = { +struct stmmac_ops dwmac1000_ops = { .core_init = dwmac1000_core_init, .rx_coe = dwmac1000_rx_coe_supported, .dump_regs = dwmac1000_dump_regs, diff --git a/trunk/drivers/net/stmmac/dwmac1000_dma.c b/trunk/drivers/net/stmmac/dwmac1000_dma.c index 2c47712d45d0..ce6163e39cd5 100644 --- a/trunk/drivers/net/stmmac/dwmac1000_dma.c +++ b/trunk/drivers/net/stmmac/dwmac1000_dma.c @@ -138,7 +138,7 @@ static void dwmac1000_dump_dma_regs(void __iomem *ioaddr) } } -const struct stmmac_dma_ops dwmac1000_dma_ops = { +struct stmmac_dma_ops dwmac1000_dma_ops = { .init = dwmac1000_dma_init, .dump_regs = dwmac1000_dump_dma_regs, .dma_mode = dwmac1000_dma_operation_mode, diff --git a/trunk/drivers/net/stmmac/dwmac100_core.c b/trunk/drivers/net/stmmac/dwmac100_core.c index c724fc36a24f..94eeccf3a8a0 100644 --- a/trunk/drivers/net/stmmac/dwmac100_core.c +++ b/trunk/drivers/net/stmmac/dwmac100_core.c @@ -168,7 +168,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode) return; } -static const struct stmmac_ops dwmac100_ops = { +struct stmmac_ops dwmac100_ops = { .core_init = dwmac100_core_init, .rx_coe = dwmac100_rx_coe_supported, .dump_regs = dwmac100_dump_mac_regs, diff --git a/trunk/drivers/net/stmmac/dwmac100_dma.c b/trunk/drivers/net/stmmac/dwmac100_dma.c index e3e224b7d9e2..96aac93b789b 100644 --- a/trunk/drivers/net/stmmac/dwmac100_dma.c +++ b/trunk/drivers/net/stmmac/dwmac100_dma.c @@ -126,7 +126,7 @@ static void dwmac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x, } } -const struct stmmac_dma_ops dwmac100_dma_ops = { +struct stmmac_dma_ops dwmac100_dma_ops = { .init = dwmac100_dma_init, .dump_regs = dwmac100_dump_dma_regs, .dma_mode = dwmac100_dma_operation_mode, diff --git a/trunk/drivers/net/stmmac/enh_desc.c b/trunk/drivers/net/stmmac/enh_desc.c index e5dfb6a30182..5d1471d8f8f6 100644 --- a/trunk/drivers/net/stmmac/enh_desc.c +++ b/trunk/drivers/net/stmmac/enh_desc.c @@ -318,7 +318,7 @@ static int enh_desc_get_rx_frame_len(struct dma_desc *p) return p->des01.erx.frame_length; } -const struct stmmac_desc_ops enh_desc_ops = { +struct stmmac_desc_ops enh_desc_ops = { .tx_status = enh_desc_get_tx_status, .rx_status = enh_desc_get_rx_status, .get_tx_len = enh_desc_get_tx_len, diff --git a/trunk/drivers/net/stmmac/norm_desc.c b/trunk/drivers/net/stmmac/norm_desc.c index cd0cc76f7a1c..0dce90cb8124 100644 --- a/trunk/drivers/net/stmmac/norm_desc.c +++ b/trunk/drivers/net/stmmac/norm_desc.c @@ -202,7 +202,7 @@ static int ndesc_get_rx_frame_len(struct dma_desc *p) return p->des01.rx.frame_length; } -const struct stmmac_desc_ops ndesc_ops = { +struct stmmac_desc_ops ndesc_ops = { .tx_status = ndesc_get_tx_status, .rx_status = ndesc_get_rx_status, .get_tx_len = ndesc_get_tx_len, diff --git a/trunk/drivers/net/stmmac/stmmac.h b/trunk/drivers/net/stmmac/stmmac.h index 79bdc2e13224..92154ff7d702 100644 --- a/trunk/drivers/net/stmmac/stmmac.h +++ b/trunk/drivers/net/stmmac/stmmac.h @@ -121,5 +121,5 @@ static inline int stmmac_claim_resource(struct platform_device *pdev) extern int stmmac_mdio_unregister(struct net_device *ndev); extern int stmmac_mdio_register(struct net_device *ndev); extern void stmmac_set_ethtool_ops(struct net_device *netdev); -extern const struct stmmac_desc_ops enh_desc_ops; -extern const struct stmmac_desc_ops ndesc_ops; +extern struct stmmac_desc_ops enh_desc_ops; +extern struct stmmac_desc_ops ndesc_ops; diff --git a/trunk/drivers/net/stmmac/stmmac_ethtool.c b/trunk/drivers/net/stmmac/stmmac_ethtool.c index 6d65482e789a..25a7e385f8ec 100644 --- a/trunk/drivers/net/stmmac/stmmac_ethtool.c +++ b/trunk/drivers/net/stmmac/stmmac_ethtool.c @@ -89,8 +89,8 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = { }; #define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats) -static void stmmac_ethtool_getdrvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) +void stmmac_ethtool_getdrvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) { struct stmmac_priv *priv = netdev_priv(dev); @@ -104,8 +104,7 @@ static void stmmac_ethtool_getdrvinfo(struct net_device *dev, info->n_stats = STMMAC_STATS_LEN; } -static int stmmac_ethtool_getsettings(struct net_device *dev, - struct ethtool_cmd *cmd) +int stmmac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) { struct stmmac_priv *priv = netdev_priv(dev); struct phy_device *phy = priv->phydev; @@ -127,8 +126,7 @@ static int stmmac_ethtool_getsettings(struct net_device *dev, return rc; } -static int stmmac_ethtool_setsettings(struct net_device *dev, - struct ethtool_cmd *cmd) +int stmmac_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd) { struct stmmac_priv *priv = netdev_priv(dev); struct phy_device *phy = priv->phydev; @@ -141,32 +139,32 @@ static int stmmac_ethtool_setsettings(struct net_device *dev, return rc; } -static u32 stmmac_ethtool_getmsglevel(struct net_device *dev) +u32 stmmac_ethtool_getmsglevel(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); return priv->msg_enable; } -static void stmmac_ethtool_setmsglevel(struct net_device *dev, u32 level) +void stmmac_ethtool_setmsglevel(struct net_device *dev, u32 level) { struct stmmac_priv *priv = netdev_priv(dev); priv->msg_enable = level; } -static int stmmac_check_if_running(struct net_device *dev) +int stmmac_check_if_running(struct net_device *dev) { if (!netif_running(dev)) return -EBUSY; return 0; } -static int stmmac_ethtool_get_regs_len(struct net_device *dev) +int stmmac_ethtool_get_regs_len(struct net_device *dev) { return REG_SPACE_SIZE; } -static void stmmac_ethtool_gregs(struct net_device *dev, +void stmmac_ethtool_gregs(struct net_device *dev, struct ethtool_regs *regs, void *space) { int i; @@ -197,7 +195,7 @@ static void stmmac_ethtool_gregs(struct net_device *dev, } } -static int stmmac_ethtool_set_tx_csum(struct net_device *netdev, u32 data) +int stmmac_ethtool_set_tx_csum(struct net_device *netdev, u32 data) { if (data) netdev->features |= NETIF_F_HW_CSUM; @@ -207,7 +205,7 @@ static int stmmac_ethtool_set_tx_csum(struct net_device *netdev, u32 data) return 0; } -static u32 stmmac_ethtool_get_rx_csum(struct net_device *dev) +u32 stmmac_ethtool_get_rx_csum(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); @@ -380,8 +378,10 @@ static struct ethtool_ops stmmac_ethtool_ops = { .get_wol = stmmac_get_wol, .set_wol = stmmac_set_wol, .get_sset_count = stmmac_get_sset_count, +#ifdef NETIF_F_TSO .get_tso = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, +#endif }; void stmmac_set_ethtool_ops(struct net_device *netdev) diff --git a/trunk/drivers/net/sundance.c b/trunk/drivers/net/sundance.c index 3ed2a67bd6d3..4283cc52a8c9 100644 --- a/trunk/drivers/net/sundance.c +++ b/trunk/drivers/net/sundance.c @@ -363,19 +363,6 @@ struct netdev_private { dma_addr_t tx_ring_dma; dma_addr_t rx_ring_dma; struct timer_list timer; /* Media monitoring timer. */ - /* ethtool extra stats */ - struct { - u64 tx_multiple_collisions; - u64 tx_single_collisions; - u64 tx_late_collisions; - u64 tx_deferred; - u64 tx_deferred_excessive; - u64 tx_aborted; - u64 tx_bcasts; - u64 rx_bcasts; - u64 tx_mcasts; - u64 rx_mcasts; - } xstats; /* Frequently used values: keep some adjacent for cache effect. */ spinlock_t lock; int msg_enable; @@ -1499,34 +1486,21 @@ static struct net_device_stats *get_stats(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); void __iomem *ioaddr = np->base; + int i; unsigned long flags; - u8 late_coll, single_coll, mult_coll; spin_lock_irqsave(&np->statlock, flags); /* The chip only need report frame silently dropped. */ dev->stats.rx_missed_errors += ioread8(ioaddr + RxMissed); dev->stats.tx_packets += ioread16(ioaddr + TxFramesOK); dev->stats.rx_packets += ioread16(ioaddr + RxFramesOK); + dev->stats.collisions += ioread8(ioaddr + StatsLateColl); + dev->stats.collisions += ioread8(ioaddr + StatsMultiColl); + dev->stats.collisions += ioread8(ioaddr + StatsOneColl); dev->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError); - - mult_coll = ioread8(ioaddr + StatsMultiColl); - np->xstats.tx_multiple_collisions += mult_coll; - single_coll = ioread8(ioaddr + StatsOneColl); - np->xstats.tx_single_collisions += single_coll; - late_coll = ioread8(ioaddr + StatsLateColl); - np->xstats.tx_late_collisions += late_coll; - dev->stats.collisions += mult_coll - + single_coll - + late_coll; - - np->xstats.tx_deferred += ioread8(ioaddr + StatsTxDefer); - np->xstats.tx_deferred_excessive += ioread8(ioaddr + StatsTxXSDefer); - np->xstats.tx_aborted += ioread8(ioaddr + StatsTxAbort); - np->xstats.tx_bcasts += ioread8(ioaddr + StatsBcastTx); - np->xstats.rx_bcasts += ioread8(ioaddr + StatsBcastRx); - np->xstats.tx_mcasts += ioread8(ioaddr + StatsMcastTx); - np->xstats.rx_mcasts += ioread8(ioaddr + StatsMcastRx); - + ioread8(ioaddr + StatsTxDefer); + for (i = StatsTxDefer; i <= StatsMcastRx; i++) + ioread8(ioaddr + i); dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow); dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16; dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow); @@ -1592,21 +1566,6 @@ static int __set_mac_addr(struct net_device *dev) return 0; } -static const struct { - const char name[ETH_GSTRING_LEN]; -} sundance_stats[] = { - { "tx_multiple_collisions" }, - { "tx_single_collisions" }, - { "tx_late_collisions" }, - { "tx_deferred" }, - { "tx_deferred_excessive" }, - { "tx_aborted" }, - { "tx_bcasts" }, - { "rx_bcasts" }, - { "tx_mcasts" }, - { "rx_mcasts" }, -}; - static int check_if_running(struct net_device *dev) { if (!netif_running(dev)) @@ -1665,42 +1624,6 @@ static void set_msglevel(struct net_device *dev, u32 val) np->msg_enable = val; } -static void get_strings(struct net_device *dev, u32 stringset, - u8 *data) -{ - if (stringset == ETH_SS_STATS) - memcpy(data, sundance_stats, sizeof(sundance_stats)); -} - -static int get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(sundance_stats); - default: - return -EOPNOTSUPP; - } -} - -static void get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct netdev_private *np = netdev_priv(dev); - int i = 0; - - get_stats(dev); - data[i++] = np->xstats.tx_multiple_collisions; - data[i++] = np->xstats.tx_single_collisions; - data[i++] = np->xstats.tx_late_collisions; - data[i++] = np->xstats.tx_deferred; - data[i++] = np->xstats.tx_deferred_excessive; - data[i++] = np->xstats.tx_aborted; - data[i++] = np->xstats.tx_bcasts; - data[i++] = np->xstats.rx_bcasts; - data[i++] = np->xstats.tx_mcasts; - data[i++] = np->xstats.rx_mcasts; -} - static const struct ethtool_ops ethtool_ops = { .begin = check_if_running, .get_drvinfo = get_drvinfo, @@ -1710,9 +1633,6 @@ static const struct ethtool_ops ethtool_ops = { .get_link = get_link, .get_msglevel = get_msglevel, .set_msglevel = set_msglevel, - .get_strings = get_strings, - .get_sset_count = get_sset_count, - .get_ethtool_stats = get_ethtool_stats, }; static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index 5b4c510dbced..943c28325444 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -69,10 +69,10 @@ #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 115 +#define TG3_MIN_NUM 114 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "October 14, 2010" +#define DRV_MODULE_RELDATE "September 30, 2010" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -1162,52 +1162,6 @@ static void tg3_mdio_fini(struct tg3 *tp) } } -static int tg3_phy_cl45_write(struct tg3 *tp, u32 devad, u32 addr, u32 val) -{ - int err; - - err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad); - if (err) - goto done; - - err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr); - if (err) - goto done; - - err = tg3_writephy(tp, MII_TG3_MMD_CTRL, - MII_TG3_MMD_CTRL_DATA_NOINC | devad); - if (err) - goto done; - - err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, val); - -done: - return err; -} - -static int tg3_phy_cl45_read(struct tg3 *tp, u32 devad, u32 addr, u32 *val) -{ - int err; - - err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad); - if (err) - goto done; - - err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr); - if (err) - goto done; - - err = tg3_writephy(tp, MII_TG3_MMD_CTRL, - MII_TG3_MMD_CTRL_DATA_NOINC | devad); - if (err) - goto done; - - err = tg3_readphy(tp, MII_TG3_MMD_ADDRESS, val); - -done: - return err; -} - /* tp->lock is held. */ static inline void tg3_generate_fw_event(struct tg3 *tp) { @@ -1584,17 +1538,6 @@ static void tg3_phy_fini(struct tg3 *tp) } } -static int tg3_phydsp_read(struct tg3 *tp, u32 reg, u32 *val) -{ - int err; - - err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); - if (!err) - err = tg3_readphy(tp, MII_TG3_DSP_RW_PORT, val); - - return err; -} - static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) { int err; @@ -1758,42 +1701,6 @@ static void tg3_phy_apply_otp(struct tg3 *tp) tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); } -static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) -{ - u32 val; - - if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) - return; - - tp->setlpicnt = 0; - - if (tp->link_config.autoneg == AUTONEG_ENABLE && - current_link_up == 1 && - (tp->link_config.active_speed == SPEED_1000 || - (tp->link_config.active_speed == SPEED_100 && - tp->link_config.active_duplex == DUPLEX_FULL))) { - u32 eeectl; - - if (tp->link_config.active_speed == SPEED_1000) - eeectl = TG3_CPMU_EEE_CTRL_EXIT_16_5_US; - else - eeectl = TG3_CPMU_EEE_CTRL_EXIT_36_US; - - tw32(TG3_CPMU_EEE_CTRL, eeectl); - - tg3_phy_cl45_read(tp, 0x7, TG3_CL45_D7_EEERES_STAT, &val); - - if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T || - val == TG3_CL45_D7_EEERES_STAT_LP_100TX) - tp->setlpicnt = 2; - } - - if (!tp->setlpicnt) { - val = tr32(TG3_CPMU_EEE_MODE); - tw32(TG3_CPMU_EEE_MODE, val & ~TG3_CPMU_EEEMD_LPI_ENABLE); - } -} - static int tg3_wait_macro_done(struct tg3 *tp) { int limit = 100; @@ -2968,44 +2875,6 @@ static void tg3_phy_copper_begin(struct tg3 *tp) tg3_writephy(tp, MII_TG3_CTRL, new_adv); } - if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) { - u32 val = 0; - - tw32(TG3_CPMU_EEE_MODE, - tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); - - /* Enable SM_DSP clock and tx 6dB coding. */ - val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | - MII_TG3_AUXCTL_ACTL_SMDSP_ENA | - MII_TG3_AUXCTL_ACTL_TX_6DB; - tg3_writephy(tp, MII_TG3_AUX_CTRL, val); - - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) && - !tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val)) - tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, - val | MII_TG3_DSP_CH34TP2_HIBW01); - - if (tp->link_config.autoneg == AUTONEG_ENABLE) { - /* Advertise 100-BaseTX EEE ability */ - if (tp->link_config.advertising & - (ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full)) - val |= TG3_CL45_D7_EEEADV_CAP_100TX; - /* Advertise 1000-BaseT EEE ability */ - if (tp->link_config.advertising & - (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full)) - val |= TG3_CL45_D7_EEEADV_CAP_1000T; - } - tg3_phy_cl45_write(tp, 0x7, TG3_CL45_D7_EEEADV_CAP, val); - - /* Turn off SM_DSP clock. */ - val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | - MII_TG3_AUXCTL_ACTL_TX_6DB; - tg3_writephy(tp, MII_TG3_AUX_CTRL, val); - } - if (tp->link_config.autoneg == AUTONEG_DISABLE && tp->link_config.speed != SPEED_INVALID) { u32 bmcr, orig_bmcr; @@ -3367,8 +3236,6 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) tw32_f(MAC_MODE, tp->mac_mode); udelay(40); - tg3_phy_eee_adjust(tp, current_link_up); - if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { /* Polled via timer. */ tw32_f(MAC_EVENT, 0); @@ -4573,11 +4440,12 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, struct tg3_rx_prodring_set *tpr, u32 opaque_key, u32 dest_idx_unmasked) { struct tg3_rx_buffer_desc *desc; - struct ring_info *map; + struct ring_info *map, *src_map; struct sk_buff *skb; dma_addr_t mapping; int skb_size, dest_idx; + src_map = NULL; switch (opaque_key) { case RXD_OPAQUE_RING_STD: dest_idx = dest_idx_unmasked & tp->rx_std_ring_mask; @@ -6219,8 +6087,7 @@ static void tg3_rx_prodring_free(struct tg3 *tp, tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i], tp->rx_pkt_map_sz); - if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && - !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { for (i = 0; i <= tp->rx_jmb_ring_mask; i++) tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i], TG3_RX_JMB_MAP_SZ); @@ -6247,7 +6114,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp, if (tpr != &tp->napi[0].prodring) { memset(&tpr->rx_std_buffers[0], 0, TG3_RX_STD_BUFF_RING_SIZE(tp)); - if (tpr->rx_jmb_buffers) + if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) memset(&tpr->rx_jmb_buffers[0], 0, TG3_RX_JMB_BUFF_RING_SIZE(tp)); goto done; @@ -6290,8 +6157,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp, } } - if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) + if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE)) goto done; memset(tpr->rx_jmb, 0, TG3_RX_JMB_RING_BYTES(tp)); @@ -6363,8 +6229,7 @@ static int tg3_rx_prodring_init(struct tg3 *tp, if (!tpr->rx_std) goto err_out; - if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && - !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { tpr->rx_jmb_buffers = kzalloc(TG3_RX_JMB_BUFF_RING_SIZE(tp), GFP_KERNEL); if (!tpr->rx_jmb_buffers) @@ -7671,9 +7536,6 @@ static void tg3_rings_reset(struct tg3 *tp) /* Disable all transmit rings but the first. */ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16; - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) - limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2; else @@ -7879,22 +7741,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(TG3_CPMU_LSPD_10MB_CLK, val); } - /* Enable MAC control of LPI */ - if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) { - tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, - TG3_CPMU_EEE_LNKIDL_PCIE_NL0 | - TG3_CPMU_EEE_LNKIDL_UART_IDL); - - tw32_f(TG3_CPMU_EEE_CTRL, - TG3_CPMU_EEE_CTRL_EXIT_20_1_US); - - tw32_f(TG3_CPMU_EEE_MODE, - TG3_CPMU_EEEMD_ERLY_L1_XIT_DET | - TG3_CPMU_EEEMD_LPI_IN_TX | - TG3_CPMU_EEEMD_LPI_IN_RX | - TG3_CPMU_EEEMD_EEE_ENABLE); - } - /* This works around an issue with Athlon chipsets on * B3 tigon3 silicon. This bit has no effect on any * other revision. But do not set this on PCI Express @@ -8703,12 +8549,6 @@ static void tg3_timer(unsigned long __opaque) if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) tg3_periodic_fetch_stats(tp); - if (tp->setlpicnt && !--tp->setlpicnt) { - u32 val = tr32(TG3_CPMU_EEE_MODE); - tw32(TG3_CPMU_EEE_MODE, - val | TG3_CPMU_EEEMD_LPI_ENABLE); - } - if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { u32 mac_stat; int phy_event; @@ -9807,9 +9647,6 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (netif_running(dev)) { cmd->speed = tp->link_config.active_speed; cmd->duplex = tp->link_config.active_duplex; - } else { - cmd->speed = SPEED_INVALID; - cmd->duplex = DUPLEX_INVALID; } cmd->phy_address = tp->phy_addr; cmd->transceiver = XCVR_INTERNAL; @@ -12546,11 +12383,6 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) } } - if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 && - tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)) - tp->phy_flags |= TG3_PHYFLG_EEE_CAP; - if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) && !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { @@ -12870,9 +12702,6 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val) case TG3_EEPROM_SB_REVISION_5: offset = TG3_EEPROM_SB_F1R5_EDH_OFF; break; - case TG3_EEPROM_SB_REVISION_6: - offset = TG3_EEPROM_SB_F1R6_EDH_OFF; - break; default: return; } diff --git a/trunk/drivers/net/tg3.h b/trunk/drivers/net/tg3.h index 8342190df0ff..f6b709a3ca32 100644 --- a/trunk/drivers/net/tg3.h +++ b/trunk/drivers/net/tg3.h @@ -1091,26 +1091,7 @@ #define CPMU_MUTEX_GNT_DRIVER 0x00001000 #define TG3_CPMU_PHY_STRAP 0x00003664 #define TG3_CPMU_PHY_STRAP_IS_SERDES 0x00000020 -/* 0x3664 --> 0x36b0 unused */ - -#define TG3_CPMU_EEE_MODE 0x000036b0 -#define TG3_CPMU_EEEMD_ERLY_L1_XIT_DET 0x00000008 -#define TG3_CPMU_EEEMD_LPI_ENABLE 0x00000080 -#define TG3_CPMU_EEEMD_LPI_IN_TX 0x00000100 -#define TG3_CPMU_EEEMD_LPI_IN_RX 0x00000200 -#define TG3_CPMU_EEEMD_EEE_ENABLE 0x00100000 -/* 0x36b4 --> 0x36b8 unused */ - -#define TG3_CPMU_EEE_LNKIDL_CTRL 0x000036bc -#define TG3_CPMU_EEE_LNKIDL_PCIE_NL0 0x01000000 -#define TG3_CPMU_EEE_LNKIDL_UART_IDL 0x00000004 -/* 0x36c0 --> 0x36d0 unused */ - -#define TG3_CPMU_EEE_CTRL 0x000036d0 -#define TG3_CPMU_EEE_CTRL_EXIT_16_5_US 0x0000019d -#define TG3_CPMU_EEE_CTRL_EXIT_36_US 0x00000384 -#define TG3_CPMU_EEE_CTRL_EXIT_20_1_US 0x000001f8 -/* 0x36d4 --> 0x3800 unused */ +/* 0x3664 --> 0x3800 unused */ /* Mbuf cluster free registers */ #define MBFREE_MODE 0x00003800 @@ -1934,7 +1915,6 @@ #define TG3_EEPROM_SB_REVISION_3 0x00030000 #define TG3_EEPROM_SB_REVISION_4 0x00040000 #define TG3_EEPROM_SB_REVISION_5 0x00050000 -#define TG3_EEPROM_SB_REVISION_6 0x00060000 #define TG3_EEPROM_MAGIC_HW 0xabcd #define TG3_EEPROM_MAGIC_HW_MSK 0xffff @@ -1954,7 +1934,6 @@ #define TG3_EEPROM_SB_F1R3_EDH_OFF 0x18 #define TG3_EEPROM_SB_F1R4_EDH_OFF 0x1c #define TG3_EEPROM_SB_F1R5_EDH_OFF 0x20 -#define TG3_EEPROM_SB_F1R6_EDH_OFF 0x4c #define TG3_EEPROM_SB_EDH_MAJ_MASK 0x00000700 #define TG3_EEPROM_SB_EDH_MAJ_SHFT 8 #define TG3_EEPROM_SB_EDH_MIN_MASK 0x000000ff @@ -2080,10 +2059,6 @@ #define MII_TG3_CTRL_AS_MASTER 0x0800 #define MII_TG3_CTRL_ENABLE_AS_MASTER 0x1000 -#define MII_TG3_MMD_CTRL 0x0d /* MMD Access Control register */ -#define MII_TG3_MMD_CTRL_DATA_NOINC 0x4000 -#define MII_TG3_MMD_ADDRESS 0x0e /* MMD Address Data register */ - #define MII_TG3_EXT_CTRL 0x10 /* Extended control register */ #define MII_TG3_EXT_CTRL_FIFO_ELASTIC 0x0001 #define MII_TG3_EXT_CTRL_LNK3_LED_MODE 0x0002 @@ -2101,8 +2076,6 @@ #define MII_TG3_DSP_TAP1 0x0001 #define MII_TG3_DSP_TAP1_AGCTGT_DFLT 0x0007 #define MII_TG3_DSP_AADJ1CH0 0x001f -#define MII_TG3_DSP_CH34TP2 0x4022 -#define MII_TG3_DSP_CH34TP2_HIBW01 0x0010 #define MII_TG3_DSP_AADJ1CH3 0x601f #define MII_TG3_DSP_AADJ1CH3_ADCCKADJ 0x0002 #define MII_TG3_DSP_EXP1_INT_STAT 0x0f01 @@ -2169,14 +2142,6 @@ #define MII_TG3_TEST1_TRIM_EN 0x0010 #define MII_TG3_TEST1_CRC_EN 0x8000 -/* Clause 45 expansion registers */ -#define TG3_CL45_D7_EEEADV_CAP 0x003c -#define TG3_CL45_D7_EEEADV_CAP_100TX 0x0002 -#define TG3_CL45_D7_EEEADV_CAP_1000T 0x0004 -#define TG3_CL45_D7_EEERES_STAT 0x803e -#define TG3_CL45_D7_EEERES_STAT_LP_100TX 0x0002 -#define TG3_CL45_D7_EEERES_STAT_LP_1000T 0x0004 - /* Fast Ethernet Tranceiver definitions */ #define MII_TG3_FET_PTEST 0x17 @@ -3021,11 +2986,9 @@ struct tg3 { #define TG3_PHYFLG_BER_BUG 0x00008000 #define TG3_PHYFLG_SERDES_PREEMPHASIS 0x00010000 #define TG3_PHYFLG_PARALLEL_DETECT 0x00020000 -#define TG3_PHYFLG_EEE_CAP 0x00040000 u32 led_ctrl; u32 phy_otp; - u32 setlpicnt; #define TG3_BPN_SIZE 24 char board_part_number[TG3_BPN_SIZE]; diff --git a/trunk/drivers/net/via-velocity.c b/trunk/drivers/net/via-velocity.c index f1995615dc84..6884813b809c 100644 --- a/trunk/drivers/net/via-velocity.c +++ b/trunk/drivers/net/via-velocity.c @@ -312,14 +312,13 @@ VELOCITY_PARAM(flow_control, "Enable flow control ability"); #define MED_LNK_DEF 0 #define MED_LNK_MIN 0 -#define MED_LNK_MAX 5 +#define MED_LNK_MAX 4 /* speed_duplex[] is used for setting the speed and duplex mode of NIC. 0: indicate autonegotiation for both speed and duplex mode 1: indicate 100Mbps half duplex mode 2: indicate 100Mbps full duplex mode 3: indicate 10Mbps half duplex mode 4: indicate 10Mbps full duplex mode - 5: indicate 1000Mbps full duplex mode Note: if EEPROM have been set to the force mode, this option is ignored @@ -618,9 +617,6 @@ static u32 velocity_get_opt_media_mode(struct velocity_info *vptr) case SPD_DPX_10_HALF: status = VELOCITY_SPEED_10; break; - case SPD_DPX_1000_FULL: - status = VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL; - break; } vptr->mii_status = status; return status; @@ -926,7 +922,6 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) /* enable AUTO-NEGO mode */ mii_set_auto_on(vptr); } else { - u16 CTRL1000; u16 ANAR; u8 CHIPGCR; @@ -941,11 +936,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) BYTE_REG_BITS_ON(CHIPGCR_FCMODE, ®s->CHIPGCR); CHIPGCR = readb(®s->CHIPGCR); - - if (mii_status & VELOCITY_SPEED_1000) - CHIPGCR |= CHIPGCR_FCGMII; - else - CHIPGCR &= ~CHIPGCR_FCGMII; + CHIPGCR &= ~CHIPGCR_FCGMII; if (mii_status & VELOCITY_DUPLEX_FULL) { CHIPGCR |= CHIPGCR_FCFDX; @@ -961,13 +952,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) BYTE_REG_BITS_ON(TCR_TB2BDIS, ®s->TCR); } - velocity_mii_read(vptr->mac_regs, MII_CTRL1000, &CTRL1000); - CTRL1000 &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - if ((mii_status & VELOCITY_SPEED_1000) && - (mii_status & VELOCITY_DUPLEX_FULL)) { - CTRL1000 |= ADVERTISE_1000FULL; - } - velocity_mii_write(vptr->mac_regs, MII_CTRL1000, CTRL1000); + MII_REG_BITS_OFF(ADVERTISE_1000FULL | ADVERTISE_1000HALF, MII_CTRL1000, vptr->mac_regs); if (!(mii_status & VELOCITY_DUPLEX_FULL) && (mii_status & VELOCITY_SPEED_10)) BYTE_REG_BITS_OFF(TESTCFG_HBDIS, ®s->TESTCFG); @@ -982,7 +967,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) ANAR |= ADVERTISE_100FULL; else ANAR |= ADVERTISE_100HALF; - } else if (mii_status & VELOCITY_SPEED_10) { + } else { if (mii_status & VELOCITY_DUPLEX_FULL) ANAR |= ADVERTISE_10FULL; else @@ -1028,9 +1013,6 @@ static void velocity_print_link_status(struct velocity_info *vptr) } else { VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name); switch (vptr->options.spd_dpx) { - case SPD_DPX_1000_FULL: - VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps full duplex\n"); - break; case SPD_DPX_100_HALF: VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n"); break; @@ -3188,37 +3170,6 @@ static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; - - cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; - if (vptr->options.spd_dpx == SPD_DPX_AUTO) { - cmd->advertising |= - ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full; - } else { - switch (vptr->options.spd_dpx) { - case SPD_DPX_1000_FULL: - cmd->advertising |= ADVERTISED_1000baseT_Full; - break; - case SPD_DPX_100_HALF: - cmd->advertising |= ADVERTISED_100baseT_Half; - break; - case SPD_DPX_100_FULL: - cmd->advertising |= ADVERTISED_100baseT_Full; - break; - case SPD_DPX_10_HALF: - cmd->advertising |= ADVERTISED_10baseT_Half; - break; - case SPD_DPX_10_FULL: - cmd->advertising |= ADVERTISED_10baseT_Full; - break; - default: - break; - } - } if (status & VELOCITY_SPEED_1000) cmd->speed = SPEED_1000; else if (status & VELOCITY_SPEED_100) @@ -3249,35 +3200,14 @@ static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd curr_status &= (~VELOCITY_LINK_FAIL); new_status |= ((cmd->autoneg) ? VELOCITY_AUTONEG_ENABLE : 0); - new_status |= ((cmd->speed == SPEED_1000) ? VELOCITY_SPEED_1000 : 0); new_status |= ((cmd->speed == SPEED_100) ? VELOCITY_SPEED_100 : 0); new_status |= ((cmd->speed == SPEED_10) ? VELOCITY_SPEED_10 : 0); new_status |= ((cmd->duplex == DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0); - if ((new_status & VELOCITY_AUTONEG_ENABLE) && - (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE))) { + if ((new_status & VELOCITY_AUTONEG_ENABLE) && (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE))) ret = -EINVAL; - } else { - enum speed_opt spd_dpx; - - if (new_status & VELOCITY_AUTONEG_ENABLE) - spd_dpx = SPD_DPX_AUTO; - else if ((new_status & VELOCITY_SPEED_1000) && - (new_status & VELOCITY_DUPLEX_FULL)) { - spd_dpx = SPD_DPX_1000_FULL; - } else if (new_status & VELOCITY_SPEED_100) - spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ? - SPD_DPX_100_FULL : SPD_DPX_100_HALF; - else if (new_status & VELOCITY_SPEED_10) - spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ? - SPD_DPX_10_FULL : SPD_DPX_10_HALF; - else - return -EOPNOTSUPP; - - vptr->options.spd_dpx = spd_dpx; - + else velocity_set_media_mode(vptr, new_status); - } return ret; } diff --git a/trunk/drivers/net/via-velocity.h b/trunk/drivers/net/via-velocity.h index aa2e69b9ff61..b5e120b0074b 100644 --- a/trunk/drivers/net/via-velocity.h +++ b/trunk/drivers/net/via-velocity.h @@ -848,7 +848,7 @@ enum velocity_owner { * Bits in CHIPGCR register */ -#define CHIPGCR_FCGMII 0x80 /* enable GMII mode */ +#define CHIPGCR_FCGMII 0x80 #define CHIPGCR_FCFDX 0x40 #define CHIPGCR_FCRESV 0x20 #define CHIPGCR_FCMODE 0x10 @@ -1390,8 +1390,7 @@ enum speed_opt { SPD_DPX_100_HALF = 1, SPD_DPX_100_FULL = 2, SPD_DPX_10_HALF = 3, - SPD_DPX_10_FULL = 4, - SPD_DPX_1000_FULL = 5 + SPD_DPX_10_FULL = 4 }; enum velocity_init_type { diff --git a/trunk/drivers/s390/net/ctcm_mpc.c b/trunk/drivers/s390/net/ctcm_mpc.c index b64881f33f23..2861e78773cb 100644 --- a/trunk/drivers/s390/net/ctcm_mpc.c +++ b/trunk/drivers/s390/net/ctcm_mpc.c @@ -540,7 +540,7 @@ void ctc_mpc_dealloc_ch(int port_num) CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG, "%s: %s: refcount = %d\n", - CTCM_FUNTAIL, dev->name, netdev_refcnt_read(dev)); + CTCM_FUNTAIL, dev->name, atomic_read(&dev->refcnt)); fsm_deltimer(&priv->restart_timer); grp->channels_terminating = 0; diff --git a/trunk/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/trunk/drivers/scsi/bnx2i/57xx_iscsi_constants.h index 1b6f86b2482d..2fceb19eb27b 100644 --- a/trunk/drivers/scsi/bnx2i/57xx_iscsi_constants.h +++ b/trunk/drivers/scsi/bnx2i/57xx_iscsi_constants.h @@ -120,8 +120,6 @@ /* additional LOM specific iSCSI license not installed */ #define ISCSI_KCQE_COMPLETION_STATUS_LOM_ISCSI_NOT_ENABLED (0x51) -#define ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY (0x80) - /* SQ/RQ/CQ DB structure sizes */ #define ISCSI_SQ_DB_SIZE (16) #define ISCSI_RQ_DB_SIZE (16) diff --git a/trunk/include/linux/can/platform/mcp251x.h b/trunk/include/linux/can/platform/mcp251x.h index 8e20540043f5..dba28268e651 100644 --- a/trunk/include/linux/can/platform/mcp251x.h +++ b/trunk/include/linux/can/platform/mcp251x.h @@ -12,6 +12,7 @@ /** * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data * @oscillator_frequency: - oscillator frequency in Hz + * @model: - actual type of chip * @board_specific_setup: - called before probing the chip (power,reset) * @transceiver_enable: - called to power on/off the transceiver * @power_enable: - called to power on/off the mcp *and* the @@ -24,6 +25,9 @@ struct mcp251x_platform_data { unsigned long oscillator_frequency; + int model; +#define CAN_MCP251X_MCP2510 0x2510 +#define CAN_MCP251X_MCP2515 0x2515 int (*board_specific_setup)(struct spi_device *spi); int (*transceiver_enable)(int enable); int (*power_enable) (int enable); diff --git a/trunk/include/linux/netpoll.h b/trunk/include/linux/netpoll.h index 79358bb712c6..50d8009be86c 100644 --- a/trunk/include/linux/netpoll.h +++ b/trunk/include/linux/netpoll.h @@ -14,6 +14,7 @@ struct netpoll { struct net_device *dev; + struct net_device *real_dev; char dev_name[IFNAMSIZ]; const char *name; void (*rx_hook)(struct netpoll *, int, char *, int); @@ -52,13 +53,7 @@ void netpoll_set_trap(int trap); void __netpoll_cleanup(struct netpoll *np); void netpoll_cleanup(struct netpoll *np); int __netpoll_rx(struct sk_buff *skb); -void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, - struct net_device *dev); -static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) -{ - netpoll_send_skb_on_dev(np, skb, np->dev); -} - +void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb); #ifdef CONFIG_NETPOLL diff --git a/trunk/include/linux/phonet.h b/trunk/include/linux/phonet.h index 26c8df786918..e27cbf931740 100644 --- a/trunk/include/linux/phonet.h +++ b/trunk/include/linux/phonet.h @@ -36,9 +36,10 @@ /* Socket options for SOL_PNPIPE level */ #define PNPIPE_ENCAP 1 #define PNPIPE_IFINDEX 2 -#define PNPIPE_PIPE_HANDLE 3 +#define PNPIPE_CREATE 3 #define PNPIPE_ENABLE 4 /* unused slot */ +#define PNPIPE_DESTROY 6 #define PNADDR_ANY 0 #define PNADDR_BROADCAST 0xFC diff --git a/trunk/include/linux/skbuff.h b/trunk/include/linux/skbuff.h index 05a358f1ba11..0b53c43ac92e 100644 --- a/trunk/include/linux/skbuff.h +++ b/trunk/include/linux/skbuff.h @@ -496,13 +496,13 @@ extern struct sk_buff *__alloc_skb(unsigned int size, static inline struct sk_buff *alloc_skb(unsigned int size, gfp_t priority) { - return __alloc_skb(size, priority, 0, NUMA_NO_NODE); + return __alloc_skb(size, priority, 0, -1); } static inline struct sk_buff *alloc_skb_fclone(unsigned int size, gfp_t priority) { - return __alloc_skb(size, priority, 1, NUMA_NO_NODE); + return __alloc_skb(size, priority, 1, -1); } extern bool skb_recycle_check(struct sk_buff *skb, int skb_size); @@ -1563,25 +1563,13 @@ static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev, return skb; } -/** - * __netdev_alloc_page - allocate a page for ps-rx on a specific device - * @dev: network device to receive on - * @gfp_mask: alloc_pages_node mask - * - * Allocate a new page. dev currently unused. - * - * %NULL is returned if there is no free memory. - */ -static inline struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask) -{ - return alloc_pages_node(NUMA_NO_NODE, gfp_mask, 0); -} +extern struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask); /** * netdev_alloc_page - allocate a page for ps-rx on a specific device * @dev: network device to receive on * - * Allocate a new page. dev currently unused. + * Allocate a new page node local to the specified device. * * %NULL is returned if there is no free memory. */ diff --git a/trunk/include/net/bluetooth/hci.h b/trunk/include/net/bluetooth/hci.h index bcbdd6d4e6dd..e30e00834340 100644 --- a/trunk/include/net/bluetooth/hci.h +++ b/trunk/include/net/bluetooth/hci.h @@ -54,7 +54,7 @@ /* HCI controller types */ #define HCI_BREDR 0x00 -#define HCI_80211 0x01 +#define HCI_AMP 0x01 /* HCI device quirks */ enum { diff --git a/trunk/include/net/net_namespace.h b/trunk/include/net/net_namespace.h index 65af9a07cf76..bd10a7908993 100644 --- a/trunk/include/net/net_namespace.h +++ b/trunk/include/net/net_namespace.h @@ -41,8 +41,6 @@ struct net { * destroy on demand */ #endif - spinlock_t rules_mod_lock; - struct list_head list; /* list of network namespaces */ struct list_head cleanup_list; /* namespaces on death row */ struct list_head exit_list; /* Use only net_mutex */ @@ -54,8 +52,7 @@ struct net { struct ctl_table_set sysctls; #endif - struct sock *rtnl; /* rtnetlink socket */ - struct sock *genl_sock; + struct net_device *loopback_dev; /* The loopback */ struct list_head dev_base_head; struct hlist_head *dev_name_head; @@ -63,9 +60,11 @@ struct net { /* core fib_rules */ struct list_head rules_ops; + spinlock_t rules_mod_lock; + struct sock *rtnl; /* rtnetlink socket */ + struct sock *genl_sock; - struct net_device *loopback_dev; /* The loopback */ struct netns_core core; struct netns_mib mib; struct netns_packet packet; @@ -85,15 +84,13 @@ struct net { struct sock *nfnl; struct sock *nfnl_stash; #endif +#ifdef CONFIG_XFRM + struct netns_xfrm xfrm; +#endif #ifdef CONFIG_WEXT_CORE struct sk_buff_head wext_nlevents; #endif struct net_generic *gen; - - /* Note : following structs are cache line aligned */ -#ifdef CONFIG_XFRM - struct netns_xfrm xfrm; -#endif }; diff --git a/trunk/include/net/netns/xfrm.h b/trunk/include/net/netns/xfrm.h index 748f91f87cd5..74f119a2829a 100644 --- a/trunk/include/net/netns/xfrm.h +++ b/trunk/include/net/netns/xfrm.h @@ -43,6 +43,10 @@ struct netns_xfrm { unsigned int policy_count[XFRM_POLICY_MAX * 2]; struct work_struct policy_hash_work; + struct dst_ops xfrm4_dst_ops; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct dst_ops xfrm6_dst_ops; +#endif struct sock *nlsk; struct sock *nlsk_stash; @@ -54,11 +58,6 @@ struct netns_xfrm { #ifdef CONFIG_SYSCTL struct ctl_table_header *sysctl_hdr; #endif - - struct dst_ops xfrm4_dst_ops; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - struct dst_ops xfrm6_dst_ops; -#endif }; #endif diff --git a/trunk/include/net/phonet/pep.h b/trunk/include/net/phonet/pep.h index b60b28c99e87..def6cfa3f451 100644 --- a/trunk/include/net/phonet/pep.h +++ b/trunk/include/net/phonet/pep.h @@ -46,8 +46,8 @@ struct pep_sock { u8 init_enable; /* auto-enable at creation */ u8 aligned; #ifdef CONFIG_PHONET_PIPECTRLR - u8 pipe_state; - struct sockaddr_pn remote_pep; + u16 remote_pep; + u8 pipe_state; #endif }; diff --git a/trunk/include/net/tipc/tipc.h b/trunk/include/net/tipc/tipc.h index 1e0645e1eed2..15af6dca0b49 100644 --- a/trunk/include/net/tipc/tipc.h +++ b/trunk/include/net/tipc/tipc.h @@ -50,6 +50,8 @@ * TIPC operating mode routines */ +u32 tipc_get_addr(void); + #define TIPC_NOT_RUNNING 0 #define TIPC_NODE_MODE 1 #define TIPC_NET_MODE 2 @@ -60,6 +62,8 @@ int tipc_attach(unsigned int *userref, tipc_mode_event, void *usr_handle); void tipc_detach(unsigned int userref); +int tipc_get_mode(void); + /* * TIPC port manipulation routines */ @@ -149,6 +153,12 @@ int tipc_disconnect(u32 portref); int tipc_shutdown(u32 ref); +int tipc_isconnected(u32 portref, int *isconnected); + +int tipc_peer(u32 portref, struct tipc_portid *peer); + +int tipc_ref_valid(u32 portref); + /* * TIPC messaging routines */ @@ -160,12 +170,38 @@ int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect); +int tipc_send_buf(u32 portref, + struct sk_buff *buf, + unsigned int dsz); + int tipc_send2name(u32 portref, struct tipc_name const *name, u32 domain, unsigned int num_sect, struct iovec const *msg_sect); +int tipc_send_buf2name(u32 portref, + struct tipc_name const *name, + u32 domain, + struct sk_buff *buf, + unsigned int dsz); + +int tipc_forward2name(u32 portref, + struct tipc_name const *name, + u32 domain, + unsigned int section_count, + struct iovec const *msg_sect, + struct tipc_portid const *origin, + unsigned int importance); + +int tipc_forward_buf2name(u32 portref, + struct tipc_name const *name, + u32 domain, + struct sk_buff *buf, + unsigned int dsz, + struct tipc_portid const *orig, + unsigned int importance); + int tipc_send2port(u32 portref, struct tipc_portid const *dest, unsigned int num_sect, @@ -176,11 +212,46 @@ int tipc_send_buf2port(u32 portref, struct sk_buff *buf, unsigned int dsz); +int tipc_forward2port(u32 portref, + struct tipc_portid const *dest, + unsigned int num_sect, + struct iovec const *msg_sect, + struct tipc_portid const *origin, + unsigned int importance); + +int tipc_forward_buf2port(u32 portref, + struct tipc_portid const *dest, + struct sk_buff *buf, + unsigned int dsz, + struct tipc_portid const *orig, + unsigned int importance); + int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, u32 domain, /* currently unused */ unsigned int section_count, struct iovec const *msg); + +#if 0 +int tipc_multicast_buf(u32 portref, + struct tipc_name_seq const *seq, + u32 domain, + void *buf, + unsigned int size); +#endif + +/* + * TIPC subscription routines + */ + +int tipc_ispublished(struct tipc_name const *name); + +/* + * Get number of available nodes within specified domain (excluding own node) + */ + +unsigned int tipc_available_nodes(const u32 domain); + #endif #endif diff --git a/trunk/include/net/tipc/tipc_port.h b/trunk/include/net/tipc/tipc_port.h index 1893aaf49426..c54917cbfa48 100644 --- a/trunk/include/net/tipc/tipc_port.h +++ b/trunk/include/net/tipc/tipc_port.h @@ -88,6 +88,8 @@ void tipc_acknowledge(u32 port_ref,u32 ack); struct tipc_port *tipc_get_port(const u32 ref); +void *tipc_get_handle(const u32 ref); + /* * The following routines require that the port be locked on entry */ diff --git a/trunk/net/bluetooth/hci_sysfs.c b/trunk/net/bluetooth/hci_sysfs.c index 8fb967beee80..1a9f0db027da 100644 --- a/trunk/net/bluetooth/hci_sysfs.c +++ b/trunk/net/bluetooth/hci_sysfs.c @@ -196,8 +196,8 @@ static inline char *host_typetostr(int type) switch (type) { case HCI_BREDR: return "BR/EDR"; - case HCI_80211: - return "802.11"; + case HCI_AMP: + return "AMP"; default: return "UNKNOWN"; } diff --git a/trunk/net/core/fib_rules.c b/trunk/net/core/fib_rules.c index 1bc3f253ba6c..21698f8c49ee 100644 --- a/trunk/net/core/fib_rules.c +++ b/trunk/net/core/fib_rules.c @@ -494,6 +494,7 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) } } + synchronize_rcu(); notify_rule_change(RTM_DELRULE, rule, ops, nlh, NETLINK_CB(skb).pid); fib_rule_put(rule); diff --git a/trunk/net/core/netpoll.c b/trunk/net/core/netpoll.c index 4e98ffac3af0..537e01afd81b 100644 --- a/trunk/net/core/netpoll.c +++ b/trunk/net/core/netpoll.c @@ -288,11 +288,11 @@ static int netpoll_owner_active(struct net_device *dev) return 0; } -void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, - struct net_device *dev) +void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) { int status = NETDEV_TX_BUSY; unsigned long tries; + struct net_device *dev = np->dev; const struct net_device_ops *ops = dev->netdev_ops; /* It is up to the caller to keep npinfo alive. */ struct netpoll_info *npinfo = np->dev->npinfo; @@ -346,7 +346,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, schedule_delayed_work(&npinfo->tx_work,0); } } -EXPORT_SYMBOL(netpoll_send_skb_on_dev); +EXPORT_SYMBOL(netpoll_send_skb); void netpoll_send_udp(struct netpoll *np, const char *msg, int len) { diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index 4e8b82e167d8..752c1972b3a7 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -247,9 +247,10 @@ EXPORT_SYMBOL(__alloc_skb); struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int length, gfp_t gfp_mask) { + int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1; struct sk_buff *skb; - skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, NUMA_NO_NODE); + skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node); if (likely(skb)) { skb_reserve(skb, NET_SKB_PAD); skb->dev = dev; @@ -258,6 +259,16 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, } EXPORT_SYMBOL(__netdev_alloc_skb); +struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask) +{ + int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1; + struct page *page; + + page = alloc_pages_node(node, gfp_mask, 0); + return page; +} +EXPORT_SYMBOL(__netdev_alloc_page); + void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, int size) { diff --git a/trunk/net/ipv4/devinet.c b/trunk/net/ipv4/devinet.c index dc94b0316b78..c2ff48fa18c7 100644 --- a/trunk/net/ipv4/devinet.c +++ b/trunk/net/ipv4/devinet.c @@ -403,9 +403,6 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) return inet_insert_ifa(ifa); } -/* Caller must hold RCU or RTNL : - * We dont take a reference on found in_device - */ struct in_device *inetdev_by_index(struct net *net, int ifindex) { struct net_device *dev; @@ -414,7 +411,7 @@ struct in_device *inetdev_by_index(struct net *net, int ifindex) rcu_read_lock(); dev = dev_get_by_index_rcu(net, ifindex); if (dev) - in_dev = rcu_dereference_rtnl(dev->ip_ptr); + in_dev = in_dev_get(dev); rcu_read_unlock(); return in_dev; } @@ -456,6 +453,8 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg goto errout; } + __in_dev_put(in_dev); + for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { if (tb[IFA_LOCAL] && diff --git a/trunk/net/ipv4/fib_frontend.c b/trunk/net/ipv4/fib_frontend.c index 36e27c2107de..919f2ad19b49 100644 --- a/trunk/net/ipv4/fib_frontend.c +++ b/trunk/net/ipv4/fib_frontend.c @@ -153,7 +153,7 @@ static void fib_flush(struct net *net) * @addr: the source address * @devref: if true, take a reference on the found device * - * If a caller uses devref=false, it should be protected by RCU, or RTNL + * If a caller uses devref=false, it should be protected by RCU */ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref) { @@ -1016,15 +1016,16 @@ static struct notifier_block fib_netdev_notifier = { static int __net_init ip_fib_net_init(struct net *net) { int err; - size_t size = sizeof(struct hlist_head) * FIB_TABLE_HASHSZ; - - /* Avoid false sharing : Use at least a full cache line */ - size = max_t(size_t, size, L1_CACHE_BYTES); + unsigned int i; - net->ipv4.fib_table_hash = kzalloc(size, GFP_KERNEL); + net->ipv4.fib_table_hash = kzalloc( + sizeof(struct hlist_head)*FIB_TABLE_HASHSZ, GFP_KERNEL); if (net->ipv4.fib_table_hash == NULL) return -ENOMEM; + for (i = 0; i < FIB_TABLE_HASHSZ; i++) + INIT_HLIST_HEAD(&net->ipv4.fib_table_hash[i]); + err = fib4_rules_init(net); if (err < 0) goto fail; diff --git a/trunk/net/ipv4/fib_hash.c b/trunk/net/ipv4/fib_hash.c index 4f1aafd3ba89..83cca68e259c 100644 --- a/trunk/net/ipv4/fib_hash.c +++ b/trunk/net/ipv4/fib_hash.c @@ -54,37 +54,36 @@ struct fib_node { struct fib_alias fn_embedded_alias; }; -#define EMBEDDED_HASH_SIZE (L1_CACHE_BYTES / sizeof(struct hlist_head)) - struct fn_zone { - struct fn_zone __rcu *fz_next; /* Next not empty zone */ - struct hlist_head __rcu *fz_hash; /* Hash table pointer */ - seqlock_t fz_lock; + struct fn_zone *fz_next; /* Next not empty zone */ + struct hlist_head *fz_hash; /* Hash table pointer */ + int fz_nent; /* Number of entries */ + + int fz_divisor; /* Hash divisor */ u32 fz_hashmask; /* (fz_divisor - 1) */ +#define FZ_HASHMASK(fz) ((fz)->fz_hashmask) - u8 fz_order; /* Zone order (0..32) */ - u8 fz_revorder; /* 32 - fz_order */ - __be32 fz_mask; /* inet_make_mask(order) */ + int fz_order; /* Zone order */ + __be32 fz_mask; #define FZ_MASK(fz) ((fz)->fz_mask) - - struct hlist_head fz_embedded_hash[EMBEDDED_HASH_SIZE]; - - int fz_nent; /* Number of entries */ - int fz_divisor; /* Hash size (mask+1) */ }; +/* NOTE. On fast computers evaluation of fz_hashmask and fz_mask + * can be cheaper than memory lookup, so that FZ_* macros are used. + */ + struct fn_hash { - struct fn_zone *fn_zones[33]; - struct fn_zone __rcu *fn_zone_list; + struct fn_zone *fn_zones[33]; + struct fn_zone *fn_zone_list; }; static inline u32 fn_hash(__be32 key, struct fn_zone *fz) { - u32 h = ntohl(key) >> fz->fz_revorder; + u32 h = ntohl(key)>>(32 - fz->fz_order); h ^= (h>>20); h ^= (h>>10); h ^= (h>>5); - h &= fz->fz_hashmask; + h &= FZ_HASHMASK(fz); return h; } @@ -93,6 +92,7 @@ static inline __be32 fz_key(__be32 dst, struct fn_zone *fz) return dst & FZ_MASK(fz); } +static DEFINE_RWLOCK(fib_hash_lock); static unsigned int fib_hash_genid; #define FZ_MAX_DIVISOR ((PAGE_SIZE<fn_hash); + hlist_del(&f->fn_hash); new_head = &fz->fz_hash[fn_hash(f->fn_key, fz)]; - hlist_add_head_rcu(&f->fn_hash, new_head); + hlist_add_head(&f->fn_hash, new_head); } } } @@ -146,14 +147,14 @@ static void fn_rehash_zone(struct fn_zone *fz) int old_divisor, new_divisor; u32 new_hashmask; - new_divisor = old_divisor = fz->fz_divisor; + old_divisor = fz->fz_divisor; switch (old_divisor) { - case EMBEDDED_HASH_SIZE: - new_divisor *= EMBEDDED_HASH_SIZE; + case 16: + new_divisor = 256; break; - case EMBEDDED_HASH_SIZE*EMBEDDED_HASH_SIZE: - new_divisor *= (EMBEDDED_HASH_SIZE/2); + case 256: + new_divisor = 1024; break; default: if ((old_divisor << 1) > FZ_MAX_DIVISOR) { @@ -174,55 +175,31 @@ static void fn_rehash_zone(struct fn_zone *fz) ht = fz_hash_alloc(new_divisor); if (ht) { - struct fn_zone nfz; - - memcpy(&nfz, fz, sizeof(nfz)); - - write_seqlock_bh(&fz->fz_lock); + write_lock_bh(&fib_hash_lock); old_ht = fz->fz_hash; - nfz.fz_hash = ht; - nfz.fz_hashmask = new_hashmask; - nfz.fz_divisor = new_divisor; - fn_rebuild_zone(&nfz, old_ht, old_divisor); - fib_hash_genid++; - rcu_assign_pointer(fz->fz_hash, ht); + fz->fz_hash = ht; fz->fz_hashmask = new_hashmask; fz->fz_divisor = new_divisor; - write_sequnlock_bh(&fz->fz_lock); + fn_rebuild_zone(fz, old_ht, old_divisor); + fib_hash_genid++; + write_unlock_bh(&fib_hash_lock); - if (old_ht != fz->fz_embedded_hash) { - synchronize_rcu(); - fz_hash_free(old_ht, old_divisor); - } + fz_hash_free(old_ht, old_divisor); } } -static void fn_free_node_rcu(struct rcu_head *head) +static inline void fn_free_node(struct fib_node * f) { - struct fib_node *f = container_of(head, struct fib_node, fn_embedded_alias.rcu); - kmem_cache_free(fn_hash_kmem, f); } -static inline void fn_free_node(struct fib_node *f) -{ - call_rcu(&f->fn_embedded_alias.rcu, fn_free_node_rcu); -} - -static void fn_free_alias_rcu(struct rcu_head *head) -{ - struct fib_alias *fa = container_of(head, struct fib_alias, rcu); - - kmem_cache_free(fn_alias_kmem, fa); -} - static inline void fn_free_alias(struct fib_alias *fa, struct fib_node *f) { fib_release_info(fa->fa_info); if (fa == &f->fn_embedded_alias) fa->fa_info = NULL; else - call_rcu(&fa->rcu, fn_free_alias_rcu); + kmem_cache_free(fn_alias_kmem, fa); } static struct fn_zone * @@ -233,30 +210,36 @@ fn_new_zone(struct fn_hash *table, int z) if (!fz) return NULL; - seqlock_init(&fz->fz_lock); - fz->fz_divisor = z ? EMBEDDED_HASH_SIZE : 1; - fz->fz_hashmask = fz->fz_divisor - 1; - fz->fz_hash = fz->fz_embedded_hash; + if (z) { + fz->fz_divisor = 16; + } else { + fz->fz_divisor = 1; + } + fz->fz_hashmask = (fz->fz_divisor - 1); + fz->fz_hash = fz_hash_alloc(fz->fz_divisor); + if (!fz->fz_hash) { + kfree(fz); + return NULL; + } fz->fz_order = z; - fz->fz_revorder = 32 - z; fz->fz_mask = inet_make_mask(z); /* Find the first not empty zone with more specific mask */ - for (i = z + 1; i <= 32; i++) + for (i=z+1; i<=32; i++) if (table->fn_zones[i]) break; - if (i > 32) { + write_lock_bh(&fib_hash_lock); + if (i>32) { /* No more specific masks, we are the first. */ - rcu_assign_pointer(fz->fz_next, - rtnl_dereference(table->fn_zone_list)); - rcu_assign_pointer(table->fn_zone_list, fz); + fz->fz_next = table->fn_zone_list; + table->fn_zone_list = fz; } else { - rcu_assign_pointer(fz->fz_next, - rtnl_dereference(table->fn_zones[i]->fz_next)); - rcu_assign_pointer(table->fn_zones[i]->fz_next, fz); + fz->fz_next = table->fn_zones[i]->fz_next; + table->fn_zones[i]->fz_next = fz; } table->fn_zones[z] = fz; fib_hash_genid++; + write_unlock_bh(&fib_hash_lock); return fz; } @@ -268,36 +251,28 @@ int fib_table_lookup(struct fib_table *tb, struct fn_zone *fz; struct fn_hash *t = (struct fn_hash *)tb->tb_data; - rcu_read_lock(); - for (fz = rcu_dereference(t->fn_zone_list); - fz != NULL; - fz = rcu_dereference(fz->fz_next)) { - struct hlist_head __rcu *head; + read_lock(&fib_hash_lock); + for (fz = t->fn_zone_list; fz; fz = fz->fz_next) { + struct hlist_head *head; struct hlist_node *node; struct fib_node *f; - __be32 k; - unsigned int seq; - - do { - seq = read_seqbegin(&fz->fz_lock); - k = fz_key(flp->fl4_dst, fz); + __be32 k = fz_key(flp->fl4_dst, fz); - head = &fz->fz_hash[fn_hash(k, fz)]; - hlist_for_each_entry_rcu(f, node, head, fn_hash) { - if (f->fn_key != k) - continue; + head = &fz->fz_hash[fn_hash(k, fz)]; + hlist_for_each_entry(f, node, head, fn_hash) { + if (f->fn_key != k) + continue; - err = fib_semantic_match(&f->fn_alias, + err = fib_semantic_match(&f->fn_alias, flp, res, fz->fz_order, fib_flags); - if (err <= 0) - goto out; - } - } while (read_seqretry(&fz->fz_lock, seq)); + if (err <= 0) + goto out; + } } err = 1; out: - rcu_read_unlock(); + read_unlock(&fib_hash_lock); return err; } @@ -319,11 +294,11 @@ void fib_table_select_default(struct fib_table *tb, last_resort = NULL; order = -1; - rcu_read_lock(); - hlist_for_each_entry_rcu(f, node, &fz->fz_hash[0], fn_hash) { + read_lock(&fib_hash_lock); + hlist_for_each_entry(f, node, &fz->fz_hash[0], fn_hash) { struct fib_alias *fa; - list_for_each_entry_rcu(fa, &f->fn_alias, fa_list) { + list_for_each_entry(fa, &f->fn_alias, fa_list) { struct fib_info *next_fi = fa->fa_info; if (fa->fa_scope != res->scope || @@ -367,7 +342,7 @@ void fib_table_select_default(struct fib_table *tb, fib_result_assign(res, last_resort); tb->tb_default = last_idx; out: - rcu_read_unlock(); + read_unlock(&fib_hash_lock); } /* Insert node F to FZ. */ @@ -375,7 +350,7 @@ static inline void fib_insert_node(struct fn_zone *fz, struct fib_node *f) { struct hlist_head *head = &fz->fz_hash[fn_hash(f->fn_key, fz)]; - hlist_add_head_rcu(&f->fn_hash, head); + hlist_add_head(&f->fn_hash, head); } /* Return the node in FZ matching KEY. */ @@ -385,7 +360,7 @@ static struct fib_node *fib_find_node(struct fn_zone *fz, __be32 key) struct hlist_node *node; struct fib_node *f; - hlist_for_each_entry_rcu(f, node, head, fn_hash) { + hlist_for_each_entry(f, node, head, fn_hash) { if (f->fn_key == key) return f; } @@ -393,17 +368,6 @@ static struct fib_node *fib_find_node(struct fn_zone *fz, __be32 key) return NULL; } - -static struct fib_alias *fib_fast_alloc(struct fib_node *f) -{ - struct fib_alias *fa = &f->fn_embedded_alias; - - if (fa->fa_info != NULL) - fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL); - return fa; -} - -/* Caller must hold RTNL. */ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) { struct fn_hash *table = (struct fn_hash *) tb->tb_data; @@ -488,6 +452,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) } if (cfg->fc_nlflags & NLM_F_REPLACE) { + struct fib_info *fi_drop; u8 state; fa = fa_first; @@ -496,25 +461,21 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) err = 0; goto out; } - err = -ENOBUFS; - new_fa = fib_fast_alloc(f); - if (new_fa == NULL) - goto out; - - new_fa->fa_tos = fa->fa_tos; - new_fa->fa_info = fi; - new_fa->fa_type = cfg->fc_type; - new_fa->fa_scope = cfg->fc_scope; + write_lock_bh(&fib_hash_lock); + fi_drop = fa->fa_info; + fa->fa_info = fi; + fa->fa_type = cfg->fc_type; + fa->fa_scope = cfg->fc_scope; state = fa->fa_state; - new_fa->fa_state = state & ~FA_S_ACCESSED; + fa->fa_state &= ~FA_S_ACCESSED; fib_hash_genid++; - list_replace_rcu(&fa->fa_list, &new_fa->fa_list); + write_unlock_bh(&fib_hash_lock); - fn_free_alias(fa, f); + fib_release_info(fi_drop); if (state & FA_S_ACCESSED) rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); - rtmsg_fib(RTM_NEWROUTE, key, new_fa, cfg->fc_dst_len, - tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE); + rtmsg_fib(RTM_NEWROUTE, key, fa, cfg->fc_dst_len, tb->tb_id, + &cfg->fc_nlinfo, NLM_F_REPLACE); return 0; } @@ -546,10 +507,12 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) f = new_f; } - new_fa = fib_fast_alloc(f); - if (new_fa == NULL) - goto out; - + new_fa = &f->fn_embedded_alias; + if (new_fa->fa_info != NULL) { + new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL); + if (new_fa == NULL) + goto out; + } new_fa->fa_info = fi; new_fa->fa_tos = tos; new_fa->fa_type = cfg->fc_type; @@ -560,11 +523,13 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) * Insert new entry to the list. */ + write_lock_bh(&fib_hash_lock); if (new_f) fib_insert_node(fz, new_f); - list_add_tail_rcu(&new_fa->fa_list, + list_add_tail(&new_fa->fa_list, (fa ? &fa->fa_list : &f->fn_alias)); fib_hash_genid++; + write_unlock_bh(&fib_hash_lock); if (new_f) fz->fz_nent++; @@ -639,12 +604,14 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) tb->tb_id, &cfg->fc_nlinfo, 0); kill_fn = 0; - list_del_rcu(&fa->fa_list); + write_lock_bh(&fib_hash_lock); + list_del(&fa->fa_list); if (list_empty(&f->fn_alias)) { - hlist_del_rcu(&f->fn_hash); + hlist_del(&f->fn_hash); kill_fn = 1; } fib_hash_genid++; + write_unlock_bh(&fib_hash_lock); if (fa->fa_state & FA_S_ACCESSED) rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); @@ -675,12 +642,14 @@ static int fn_flush_list(struct fn_zone *fz, int idx) struct fib_info *fi = fa->fa_info; if (fi && (fi->fib_flags&RTNH_F_DEAD)) { - list_del_rcu(&fa->fa_list); + write_lock_bh(&fib_hash_lock); + list_del(&fa->fa_list); if (list_empty(&f->fn_alias)) { - hlist_del_rcu(&f->fn_hash); + hlist_del(&f->fn_hash); kill_f = 1; } fib_hash_genid++; + write_unlock_bh(&fib_hash_lock); fn_free_alias(fa, f); found++; @@ -694,16 +663,13 @@ static int fn_flush_list(struct fn_zone *fz, int idx) return found; } -/* caller must hold RTNL. */ int fib_table_flush(struct fib_table *tb) { struct fn_hash *table = (struct fn_hash *) tb->tb_data; struct fn_zone *fz; int found = 0; - for (fz = rtnl_dereference(table->fn_zone_list); - fz != NULL; - fz = rtnl_dereference(fz->fz_next)) { + for (fz = table->fn_zone_list; fz; fz = fz->fz_next) { int i; for (i = fz->fz_divisor - 1; i >= 0; i--) @@ -725,10 +691,10 @@ fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb, s_i = cb->args[4]; i = 0; - hlist_for_each_entry_rcu(f, node, head, fn_hash) { + hlist_for_each_entry(f, node, head, fn_hash) { struct fib_alias *fa; - list_for_each_entry_rcu(fa, &f->fn_alias, fa_list) { + list_for_each_entry(fa, &f->fn_alias, fa_list) { if (i < s_i) goto next; @@ -746,7 +712,7 @@ fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb, cb->args[4] = i; return -1; } -next: + next: i++; } } @@ -781,26 +747,23 @@ fn_hash_dump_zone(struct sk_buff *skb, struct netlink_callback *cb, int fib_table_dump(struct fib_table *tb, struct sk_buff *skb, struct netlink_callback *cb) { - int m = 0, s_m; + int m, s_m; struct fn_zone *fz; struct fn_hash *table = (struct fn_hash *)tb->tb_data; s_m = cb->args[2]; - rcu_read_lock(); - for (fz = rcu_dereference(table->fn_zone_list); - fz != NULL; - fz = rcu_dereference(fz->fz_next), m++) { - if (m < s_m) - continue; + read_lock(&fib_hash_lock); + for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) { + if (m < s_m) continue; if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) { cb->args[2] = m; - rcu_read_unlock(); + read_unlock(&fib_hash_lock); return -1; } memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0])); } - rcu_read_unlock(); + read_unlock(&fib_hash_lock); cb->args[2] = m; return skb->len; } @@ -863,9 +826,8 @@ static struct fib_alias *fib_get_first(struct seq_file *seq) iter->genid = fib_hash_genid; iter->valid = 1; - for (iter->zone = rcu_dereference(table->fn_zone_list); - iter->zone != NULL; - iter->zone = rcu_dereference(iter->zone->fz_next)) { + for (iter->zone = table->fn_zone_list; iter->zone; + iter->zone = iter->zone->fz_next) { int maxslot; if (!iter->zone->fz_nent) @@ -950,7 +912,7 @@ static struct fib_alias *fib_get_next(struct seq_file *seq) } } - iter->zone = rcu_dereference(iter->zone->fz_next); + iter->zone = iter->zone->fz_next; if (!iter->zone) goto out; @@ -989,11 +951,11 @@ static struct fib_alias *fib_get_idx(struct seq_file *seq, loff_t pos) } static void *fib_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(RCU) + __acquires(fib_hash_lock) { void *v = NULL; - rcu_read_lock(); + read_lock(&fib_hash_lock); if (fib_get_table(seq_file_net(seq), RT_TABLE_MAIN)) v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; return v; @@ -1006,16 +968,15 @@ static void *fib_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void fib_seq_stop(struct seq_file *seq, void *v) - __releases(RCU) + __releases(fib_hash_lock) { - rcu_read_unlock(); + read_unlock(&fib_hash_lock); } static unsigned fib_flag_trans(int type, __be32 mask, struct fib_info *fi) { static const unsigned type2flags[RTN_MAX + 1] = { - [7] = RTF_REJECT, - [8] = RTF_REJECT, + [7] = RTF_REJECT, [8] = RTF_REJECT, }; unsigned flags = type2flags[type]; diff --git a/trunk/net/ipv4/fib_lookup.h b/trunk/net/ipv4/fib_lookup.h index 5072d8effd5d..b9c9a9f2aee5 100644 --- a/trunk/net/ipv4/fib_lookup.h +++ b/trunk/net/ipv4/fib_lookup.h @@ -12,7 +12,9 @@ struct fib_alias { u8 fa_type; u8 fa_scope; u8 fa_state; +#ifdef CONFIG_IP_FIB_TRIE struct rcu_head rcu; +#endif }; #define FA_S_ACCESSED 0x01 diff --git a/trunk/net/ipv4/fib_semantics.c b/trunk/net/ipv4/fib_semantics.c index 6734c9cab248..0f80dfc2f7fb 100644 --- a/trunk/net/ipv4/fib_semantics.c +++ b/trunk/net/ipv4/fib_semantics.c @@ -590,29 +590,32 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, if (!dev) goto out; dev_hold(dev); - err = (dev->flags & IFF_UP) ? 0 : -ENETDOWN; + err = -ENETDOWN; + if (!(dev->flags & IFF_UP)) + goto out; + err = 0; +out: + rcu_read_unlock(); + return err; } else { struct in_device *in_dev; if (nh->nh_flags & (RTNH_F_PERVASIVE | RTNH_F_ONLINK)) return -EINVAL; - rcu_read_lock(); - err = -ENODEV; in_dev = inetdev_by_index(net, nh->nh_oif); if (in_dev == NULL) - goto out; - err = -ENETDOWN; - if (!(in_dev->dev->flags & IFF_UP)) - goto out; + return -ENODEV; + if (!(in_dev->dev->flags & IFF_UP)) { + in_dev_put(in_dev); + return -ENETDOWN; + } nh->nh_dev = in_dev->dev; dev_hold(nh->nh_dev); nh->nh_scope = RT_SCOPE_HOST; - err = 0; + in_dev_put(in_dev); } -out: - rcu_read_unlock(); - return err; + return 0; } static inline unsigned int fib_laddr_hashfn(__be32 val) diff --git a/trunk/net/ipv4/fib_trie.c b/trunk/net/ipv4/fib_trie.c index 31494f335686..271c89bdf049 100644 --- a/trunk/net/ipv4/fib_trie.c +++ b/trunk/net/ipv4/fib_trie.c @@ -1384,7 +1384,8 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp, t_key cindex = 0; int current_prefix_length = KEYLENGTH; struct tnode *cn; - t_key pref_mismatch; + t_key node_prefix, key_prefix, pref_mismatch; + int mp; rcu_read_lock(); @@ -1499,7 +1500,10 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp, * matching prefix. */ - pref_mismatch = mask_pfx(cn->key ^ key, cn->pos); + node_prefix = mask_pfx(cn->key, cn->pos); + key_prefix = mask_pfx(key, cn->pos); + pref_mismatch = key_prefix^node_prefix; + mp = 0; /* * In short: If skipped bits in this node do not match @@ -1507,9 +1511,13 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp, * state.directly. */ if (pref_mismatch) { - int mp = KEYLENGTH - fls(pref_mismatch); + while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) { + mp++; + pref_mismatch = pref_mismatch << 1; + } + key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp); - if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0) + if (key_prefix != 0) goto backtrace; if (current_prefix_length >= cn->pos) diff --git a/trunk/net/ipv4/igmp.c b/trunk/net/ipv4/igmp.c index c8877c6c7216..25f339672b28 100644 --- a/trunk/net/ipv4/igmp.c +++ b/trunk/net/ipv4/igmp.c @@ -1418,7 +1418,6 @@ void ip_mc_destroy_dev(struct in_device *in_dev) write_unlock_bh(&in_dev->mc_list_lock); } -/* RTNL is locked */ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr) { struct flowi fl = { .nl_u = { .ip4_u = @@ -1429,12 +1428,15 @@ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr) if (imr->imr_ifindex) { idev = inetdev_by_index(net, imr->imr_ifindex); + if (idev) + __in_dev_put(idev); return idev; } if (imr->imr_address.s_addr) { - dev = __ip_dev_find(net, imr->imr_address.s_addr, false); + dev = ip_dev_find(net, imr->imr_address.s_addr); if (!dev) return NULL; + dev_put(dev); } if (!dev && !ip_route_output_key(net, &rt, &fl)) { diff --git a/trunk/net/ipv4/ip_gre.c b/trunk/net/ipv4/ip_gre.c index d0ffcbe369b7..9d421f4cf3ef 100644 --- a/trunk/net/ipv4/ip_gre.c +++ b/trunk/net/ipv4/ip_gre.c @@ -1245,8 +1245,10 @@ static int ipgre_close(struct net_device *dev) if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) { struct in_device *in_dev; in_dev = inetdev_by_index(dev_net(dev), t->mlink); - if (in_dev) + if (in_dev) { ip_mc_dec_group(in_dev, t->parms.iph.daddr); + in_dev_put(in_dev); + } } return 0; } diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index ff98983d2a45..0755aa4af86c 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -2124,7 +2124,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, ipv4_is_loopback(saddr)) goto martian_source; - if (ipv4_is_lbcast(daddr) || (saddr == 0 && daddr == 0)) + if (daddr == htonl(0xFFFFFFFF) || (saddr == 0 && daddr == 0)) goto brd_input; /* Accept zero addresses only to limited broadcast; @@ -2133,7 +2133,8 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, if (ipv4_is_zeronet(saddr)) goto martian_source; - if (ipv4_is_zeronet(daddr) || ipv4_is_loopback(daddr)) + if (ipv4_is_lbcast(daddr) || ipv4_is_zeronet(daddr) || + ipv4_is_loopback(daddr)) goto martian_destination; /* @@ -2366,11 +2367,11 @@ static int __mkroute_output(struct rtable **result, if (ipv4_is_loopback(fl->fl4_src) && !(dev_out->flags & IFF_LOOPBACK)) return -EINVAL; - if (ipv4_is_lbcast(fl->fl4_dst)) + if (fl->fl4_dst == htonl(0xFFFFFFFF)) res->type = RTN_BROADCAST; else if (ipv4_is_multicast(fl->fl4_dst)) res->type = RTN_MULTICAST; - else if (ipv4_is_zeronet(fl->fl4_dst)) + else if (ipv4_is_lbcast(fl->fl4_dst) || ipv4_is_zeronet(fl->fl4_dst)) return -EINVAL; if (dev_out->flags & IFF_LOOPBACK) @@ -2529,7 +2530,7 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, if (oldflp->oif == 0 && (ipv4_is_multicast(oldflp->fl4_dst) || - ipv4_is_lbcast(oldflp->fl4_dst))) { + oldflp->fl4_dst == htonl(0xFFFFFFFF))) { /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ dev_out = __ip_dev_find(net, oldflp->fl4_src, false); if (dev_out == NULL) @@ -2573,7 +2574,7 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, goto out; /* Wrong error code */ if (ipv4_is_local_multicast(oldflp->fl4_dst) || - ipv4_is_lbcast(oldflp->fl4_dst)) { + oldflp->fl4_dst == htonl(0xFFFFFFFF)) { if (!fl.fl4_src) fl.fl4_src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK); diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index ee0df4817498..e4fbdae066d5 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -2495,7 +2495,7 @@ static void tcp_timeout_skbs(struct sock *sk) /* Mark head of queue up as lost. With RFC3517 SACK, the packets is * is against sacked "cnt", otherwise it's against facked "cnt" */ -static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) +static void tcp_mark_head_lost(struct sock *sk, int packets) { struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; @@ -2503,13 +2503,13 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) int err; unsigned int mss; + if (packets == 0) + return; + WARN_ON(packets > tp->packets_out); if (tp->lost_skb_hint) { skb = tp->lost_skb_hint; cnt = tp->lost_cnt_hint; - /* Head already handled? */ - if (mark_head && skb != tcp_write_queue_head(sk)) - return; } else { skb = tcp_write_queue_head(sk); cnt = 0; @@ -2544,9 +2544,6 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) } tcp_skb_mark_lost(tp, skb); - - if (mark_head) - break; } tcp_verify_left_out(tp); } @@ -2558,18 +2555,17 @@ static void tcp_update_scoreboard(struct sock *sk, int fast_rexmit) struct tcp_sock *tp = tcp_sk(sk); if (tcp_is_reno(tp)) { - tcp_mark_head_lost(sk, 1, 1); + tcp_mark_head_lost(sk, 1); } else if (tcp_is_fack(tp)) { int lost = tp->fackets_out - tp->reordering; if (lost <= 0) lost = 1; - tcp_mark_head_lost(sk, lost, 0); + tcp_mark_head_lost(sk, lost); } else { int sacked_upto = tp->sacked_out - tp->reordering; - if (sacked_upto >= 0) - tcp_mark_head_lost(sk, sacked_upto, 0); - else if (fast_rexmit) - tcp_mark_head_lost(sk, 1, 1); + if (sacked_upto < fast_rexmit) + sacked_upto = fast_rexmit; + tcp_mark_head_lost(sk, sacked_upto); } tcp_timeout_skbs(sk); @@ -2975,7 +2971,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag) before(tp->snd_una, tp->high_seq) && icsk->icsk_ca_state != TCP_CA_Open && tp->fackets_out > tp->reordering) { - tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering, 0); + tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSS); } diff --git a/trunk/net/ipv4/tcp_timer.c b/trunk/net/ipv4/tcp_timer.c index 74a6aa003657..f3c8c6c019ae 100644 --- a/trunk/net/ipv4/tcp_timer.c +++ b/trunk/net/ipv4/tcp_timer.c @@ -367,19 +367,18 @@ void tcp_retransmit_timer(struct sock *sk) if (icsk->icsk_retransmits == 0) { int mib_idx; - if (icsk->icsk_ca_state == TCP_CA_Recovery) { + if (icsk->icsk_ca_state == TCP_CA_Disorder) { + if (tcp_is_sack(tp)) + mib_idx = LINUX_MIB_TCPSACKFAILURES; + else + mib_idx = LINUX_MIB_TCPRENOFAILURES; + } else if (icsk->icsk_ca_state == TCP_CA_Recovery) { if (tcp_is_sack(tp)) mib_idx = LINUX_MIB_TCPSACKRECOVERYFAIL; else mib_idx = LINUX_MIB_TCPRENORECOVERYFAIL; } else if (icsk->icsk_ca_state == TCP_CA_Loss) { mib_idx = LINUX_MIB_TCPLOSSFAILURES; - } else if ((icsk->icsk_ca_state == TCP_CA_Disorder) || - tp->sacked_out) { - if (tcp_is_sack(tp)) - mib_idx = LINUX_MIB_TCPSACKFAILURES; - else - mib_idx = LINUX_MIB_TCPRENOFAILURES; } else { mib_idx = LINUX_MIB_TCPTIMEOUTS; } diff --git a/trunk/net/ipv6/fib6_rules.c b/trunk/net/ipv6/fib6_rules.c index d829874d8946..b1108ede18e1 100644 --- a/trunk/net/ipv6/fib6_rules.c +++ b/trunk/net/ipv6/fib6_rules.c @@ -34,10 +34,11 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, { struct fib_lookup_arg arg = { .lookup_ptr = lookup, - .flags = FIB_LOOKUP_NOREF, }; fib_rules_lookup(net->ipv6.fib6_rules_ops, fl, flags, &arg); + if (arg.rule) + fib_rule_put(arg.rule); if (arg.result) return arg.result; diff --git a/trunk/net/ipv6/ip6_fib.c b/trunk/net/ipv6/ip6_fib.c index de382114609b..b6a585909d35 100644 --- a/trunk/net/ipv6/ip6_fib.c +++ b/trunk/net/ipv6/ip6_fib.c @@ -1500,18 +1500,15 @@ static void fib6_gc_timer_cb(unsigned long arg) static int __net_init fib6_net_init(struct net *net) { - size_t size = sizeof(struct hlist_head) * FIB6_TABLE_HASHSZ; - setup_timer(&net->ipv6.ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)net); net->ipv6.rt6_stats = kzalloc(sizeof(*net->ipv6.rt6_stats), GFP_KERNEL); if (!net->ipv6.rt6_stats) goto out_timer; - /* Avoid false sharing : Use at least a full cache line */ - size = max_t(size_t, size, L1_CACHE_BYTES); - - net->ipv6.fib_table_hash = kzalloc(size, GFP_KERNEL); + net->ipv6.fib_table_hash = kcalloc(FIB6_TABLE_HASHSZ, + sizeof(*net->ipv6.fib_table_hash), + GFP_KERNEL); if (!net->ipv6.fib_table_hash) goto out_rt6_stats; diff --git a/trunk/net/phonet/pep.c b/trunk/net/phonet/pep.c index 3e60f2e4e6c2..f818f76d297d 100644 --- a/trunk/net/phonet/pep.c +++ b/trunk/net/phonet/pep.c @@ -88,6 +88,15 @@ static int pep_reply(struct sock *sk, struct sk_buff *oskb, const struct pnpipehdr *oph = pnp_hdr(oskb); struct pnpipehdr *ph; struct sk_buff *skb; +#ifdef CONFIG_PHONET_PIPECTRLR + const struct phonethdr *hdr = pn_hdr(oskb); + struct sockaddr_pn spn = { + .spn_family = AF_PHONET, + .spn_resource = 0xD9, + .spn_dev = hdr->pn_sdev, + .spn_obj = hdr->pn_sobj, + }; +#endif skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority); if (!skb) @@ -105,7 +114,11 @@ static int pep_reply(struct sock *sk, struct sk_buff *oskb, ph->pipe_handle = oph->pipe_handle; ph->error_code = code; +#ifdef CONFIG_PHONET_PIPECTRLR + return pn_skb_send(sk, skb, &spn); +#else return pn_skb_send(sk, skb, &pipe_srv); +#endif } #define PAD 0x00 @@ -175,13 +188,18 @@ static int pipe_get_flow_info(struct sock *sk, struct sk_buff *skb, return 0; } -static int pipe_handler_send_req(struct sock *sk, u8 utid, - u8 msg_id, gfp_t priority) +static int pipe_handler_send_req(struct sock *sk, u16 dobj, u8 utid, + u8 msg_id, u8 p_handle, gfp_t priority) { int len; struct pnpipehdr *ph; struct sk_buff *skb; - struct pep_sock *pn = pep_sk(sk); + struct sockaddr_pn spn = { + .spn_family = AF_PHONET, + .spn_resource = 0xD9, + .spn_dev = pn_dev(dobj), + .spn_obj = pn_obj(dobj), + }; static const u8 data[4] = { PAD, PAD, PAD, PAD, @@ -217,25 +235,30 @@ static int pipe_handler_send_req(struct sock *sk, u8 utid, ph = pnp_hdr(skb); ph->utid = utid; ph->message_id = msg_id; - ph->pipe_handle = pn->pipe_handle; + ph->pipe_handle = p_handle; ph->error_code = PN_PIPE_NO_ERROR; - return pn_skb_send(sk, skb, &pn->remote_pep); + return pn_skb_send(sk, skb, &spn); } -static int pipe_handler_send_created_ind(struct sock *sk, - u8 utid, u8 msg_id) +static int pipe_handler_send_created_ind(struct sock *sk, u16 dobj, + u8 utid, u8 p_handle, u8 msg_id, u8 tx_fc, u8 rx_fc) { int err_code; struct pnpipehdr *ph; struct sk_buff *skb; + struct sockaddr_pn spn = { + .spn_family = AF_PHONET, + .spn_resource = 0xD9, + .spn_dev = pn_dev(dobj), + .spn_obj = pn_obj(dobj), + }; - struct pep_sock *pn = pep_sk(sk); static u8 data[4] = { 0x03, 0x04, }; - data[2] = pn->tx_fc; - data[3] = pn->rx_fc; + data[2] = tx_fc; + data[3] = rx_fc; /* * actually, below is number of sub-blocks and not error code. @@ -259,18 +282,24 @@ static int pipe_handler_send_created_ind(struct sock *sk, ph = pnp_hdr(skb); ph->utid = utid; ph->message_id = msg_id; - ph->pipe_handle = pn->pipe_handle; + ph->pipe_handle = p_handle; ph->error_code = err_code; - return pn_skb_send(sk, skb, &pn->remote_pep); + return pn_skb_send(sk, skb, &spn); } -static int pipe_handler_send_ind(struct sock *sk, u8 utid, u8 msg_id) +static int pipe_handler_send_ind(struct sock *sk, u16 dobj, u8 utid, + u8 p_handle, u8 msg_id) { int err_code; struct pnpipehdr *ph; struct sk_buff *skb; - struct pep_sock *pn = pep_sk(sk); + struct sockaddr_pn spn = { + .spn_family = AF_PHONET, + .spn_resource = 0xD9, + .spn_dev = pn_dev(dobj), + .spn_obj = pn_obj(dobj), + }; /* * actually, below is a filler. @@ -292,14 +321,15 @@ static int pipe_handler_send_ind(struct sock *sk, u8 utid, u8 msg_id) ph = pnp_hdr(skb); ph->utid = utid; ph->message_id = msg_id; - ph->pipe_handle = pn->pipe_handle; + ph->pipe_handle = p_handle; ph->error_code = err_code; - return pn_skb_send(sk, skb, &pn->remote_pep); + return pn_skb_send(sk, skb, &spn); } static int pipe_handler_enable_pipe(struct sock *sk, int enable) { + struct pep_sock *pn = pep_sk(sk); int utid, req; if (enable) { @@ -309,7 +339,34 @@ static int pipe_handler_enable_pipe(struct sock *sk, int enable) utid = PNS_PIPE_DISABLE_UTID; req = PNS_PEP_DISABLE_REQ; } - return pipe_handler_send_req(sk, utid, req, GFP_ATOMIC); + return pipe_handler_send_req(sk, pn->pn_sk.sobject, utid, req, + pn->pipe_handle, GFP_ATOMIC); +} + +static int pipe_handler_create_pipe(struct sock *sk, int pipe_handle, int cmd) +{ + int ret; + struct pep_sock *pn = pep_sk(sk); + + switch (cmd) { + case PNPIPE_CREATE: + ret = pipe_handler_send_req(sk, pn->pn_sk.sobject, + PNS_PEP_CONNECT_UTID, PNS_PEP_CONNECT_REQ, + pipe_handle, GFP_ATOMIC); + break; + + case PNPIPE_DESTROY: + ret = pipe_handler_send_req(sk, pn->remote_pep, + PNS_PEP_DISCONNECT_UTID, + PNS_PEP_DISCONNECT_REQ, + pn->pipe_handle, GFP_ATOMIC); + break; + + default: + ret = -EINVAL; + } + + return ret; } #endif @@ -377,6 +434,14 @@ static int pipe_snd_status(struct sock *sk, u8 type, u8 status, gfp_t priority) struct pep_sock *pn = pep_sk(sk); struct pnpipehdr *ph; struct sk_buff *skb; +#ifdef CONFIG_PHONET_PIPECTRLR + struct sockaddr_pn spn = { + .spn_family = AF_PHONET, + .spn_resource = 0xD9, + .spn_dev = pn_dev(pn->remote_pep), + .spn_obj = pn_obj(pn->remote_pep), + }; +#endif skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority); if (!skb) @@ -397,7 +462,7 @@ static int pipe_snd_status(struct sock *sk, u8 type, u8 status, gfp_t priority) ph->data[4] = status; #ifdef CONFIG_PHONET_PIPECTRLR - return pn_skb_send(sk, skb, &pn->remote_pep); + return pn_skb_send(sk, skb, &spn); #else return pn_skb_send(sk, skb, &pipe_srv); #endif @@ -517,6 +582,12 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) struct pnpipehdr *hdr = pnp_hdr(skb); struct sk_buff_head *queue; int err = 0; +#ifdef CONFIG_PHONET_PIPECTRLR + struct phonethdr *ph = pn_hdr(skb); + static u8 host_pref_rx_fc[3], host_req_tx_fc[3]; + u8 remote_pref_rx_fc[3], remote_req_tx_fc[3]; + u8 negotiated_rx_fc, negotiated_tx_fc; +#endif BUG_ON(sk->sk_state == TCP_CLOSE_WAIT); @@ -525,6 +596,40 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE); break; +#ifdef CONFIG_PHONET_PIPECTRLR + case PNS_PEP_CONNECT_RESP: + if ((ph->pn_sdev == pn_dev(pn->remote_pep)) && + (ph->pn_sobj == pn_obj(pn->remote_pep))) { + pipe_get_flow_info(sk, skb, remote_pref_rx_fc, + remote_req_tx_fc); + + negotiated_tx_fc = pipe_negotiate_fc(remote_req_tx_fc, + host_pref_rx_fc, + sizeof(host_pref_rx_fc)); + negotiated_rx_fc = pipe_negotiate_fc(host_req_tx_fc, + remote_pref_rx_fc, + sizeof(host_pref_rx_fc)); + + pn->pipe_state = PIPE_DISABLED; + pipe_handler_send_created_ind(sk, pn->remote_pep, + PNS_PIPE_CREATED_IND_UTID, + pn->pipe_handle, PNS_PIPE_CREATED_IND, + negotiated_tx_fc, negotiated_rx_fc); + pipe_handler_send_created_ind(sk, pn->pn_sk.sobject, + PNS_PIPE_CREATED_IND_UTID, + pn->pipe_handle, PNS_PIPE_CREATED_IND, + negotiated_tx_fc, negotiated_rx_fc); + } else { + pipe_handler_send_req(sk, pn->remote_pep, + PNS_PEP_CONNECT_UTID, + PNS_PEP_CONNECT_REQ, pn->pipe_handle, + GFP_ATOMIC); + pipe_get_flow_info(sk, skb, host_pref_rx_fc, + host_req_tx_fc); + } + break; +#endif + case PNS_PEP_DISCONNECT_REQ: pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); sk->sk_state = TCP_CLOSE_WAIT; @@ -535,7 +640,10 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) #ifdef CONFIG_PHONET_PIPECTRLR case PNS_PEP_DISCONNECT_RESP: pn->pipe_state = PIPE_IDLE; - sk->sk_state = TCP_CLOSE; + pipe_handler_send_req(sk, pn->pn_sk.sobject, + PNS_PEP_DISCONNECT_UTID, + PNS_PEP_DISCONNECT_REQ, pn->pipe_handle, + GFP_KERNEL); break; #endif @@ -546,18 +654,21 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) #ifdef CONFIG_PHONET_PIPECTRLR case PNS_PEP_ENABLE_RESP: - pn->pipe_state = PIPE_ENABLED; - pipe_handler_send_ind(sk, PNS_PIPE_ENABLED_IND_UTID, - PNS_PIPE_ENABLED_IND); + if ((ph->pn_sdev == pn_dev(pn->remote_pep)) && + (ph->pn_sobj == pn_obj(pn->remote_pep))) { + pn->pipe_state = PIPE_ENABLED; + pipe_handler_send_ind(sk, pn->remote_pep, + PNS_PIPE_ENABLED_IND_UTID, + pn->pipe_handle, PNS_PIPE_ENABLED_IND); + pipe_handler_send_ind(sk, pn->pn_sk.sobject, + PNS_PIPE_ENABLED_IND_UTID, + pn->pipe_handle, PNS_PIPE_ENABLED_IND); + } else + pipe_handler_send_req(sk, pn->remote_pep, + PNS_PIPE_ENABLE_UTID, + PNS_PEP_ENABLE_REQ, pn->pipe_handle, + GFP_KERNEL); - if (!pn_flow_safe(pn->tx_fc)) { - atomic_set(&pn->tx_credits, 1); - sk->sk_write_space(sk); - } - if (sk->sk_state == TCP_ESTABLISHED) - break; /* Nothing to do */ - sk->sk_state = TCP_ESTABLISHED; - pipe_grant_credits(sk); break; #endif @@ -581,12 +692,22 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) #ifdef CONFIG_PHONET_PIPECTRLR case PNS_PEP_DISABLE_RESP: - pn->pipe_state = PIPE_DISABLED; - atomic_set(&pn->tx_credits, 0); - pipe_handler_send_ind(sk, PNS_PIPE_DISABLED_IND_UTID, - PNS_PIPE_DISABLED_IND); - sk->sk_state = TCP_SYN_RECV; - pn->rx_credits = 0; + if ((ph->pn_sdev == pn_dev(pn->remote_pep)) && + (ph->pn_sobj == pn_obj(pn->remote_pep))) { + pn->pipe_state = PIPE_DISABLED; + pipe_handler_send_ind(sk, pn->remote_pep, + PNS_PIPE_DISABLED_IND_UTID, + pn->pipe_handle, + PNS_PIPE_DISABLED_IND); + pipe_handler_send_ind(sk, pn->pn_sk.sobject, + PNS_PIPE_DISABLED_IND_UTID, + pn->pipe_handle, + PNS_PIPE_DISABLED_IND); + } else + pipe_handler_send_req(sk, pn->remote_pep, + PNS_PIPE_DISABLE_UTID, + PNS_PEP_DISABLE_REQ, pn->pipe_handle, + GFP_KERNEL); break; #endif @@ -681,42 +802,6 @@ static void pipe_destruct(struct sock *sk) skb_queue_purge(&pn->ctrlreq_queue); } -#ifdef CONFIG_PHONET_PIPECTRLR -static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb) -{ - struct pep_sock *pn = pep_sk(sk); - u8 host_pref_rx_fc[3] = {3, 2, 1}, host_req_tx_fc[3] = {3, 2, 1}; - u8 remote_pref_rx_fc[3], remote_req_tx_fc[3]; - u8 negotiated_rx_fc, negotiated_tx_fc; - int ret; - - pipe_get_flow_info(sk, skb, remote_pref_rx_fc, - remote_req_tx_fc); - negotiated_tx_fc = pipe_negotiate_fc(remote_req_tx_fc, - host_pref_rx_fc, - sizeof(host_pref_rx_fc)); - negotiated_rx_fc = pipe_negotiate_fc(host_req_tx_fc, - remote_pref_rx_fc, - sizeof(host_pref_rx_fc)); - - pn->pipe_state = PIPE_DISABLED; - sk->sk_state = TCP_SYN_RECV; - sk->sk_backlog_rcv = pipe_do_rcv; - sk->sk_destruct = pipe_destruct; - pn->rx_credits = 0; - pn->rx_fc = negotiated_rx_fc; - pn->tx_fc = negotiated_tx_fc; - sk->sk_state_change(sk); - - ret = pipe_handler_send_created_ind(sk, - PNS_PIPE_CREATED_IND_UTID, - PNS_PIPE_CREATED_IND - ); - - return ret; -} -#endif - static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) { struct sock *newsk; @@ -799,6 +884,9 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL; newpn->init_enable = enabled; newpn->aligned = aligned; +#ifdef CONFIG_PHONET_PIPECTRLR + newpn->remote_pep = pn->remote_pep; +#endif BUG_ON(!skb_queue_empty(&newsk->sk_receive_queue)); skb_queue_head(&newsk->sk_receive_queue, skb); @@ -880,12 +968,6 @@ static int pep_do_rcv(struct sock *sk, struct sk_buff *skb) err = pep_connreq_rcv(sk, skb); break; -#ifdef CONFIG_PHONET_PIPECTRLR - case PNS_PEP_CONNECT_RESP: - err = pep_connresp_rcv(sk, skb); - break; -#endif - case PNS_PEP_DISCONNECT_REQ: pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); break; @@ -950,18 +1032,6 @@ static void pep_sock_close(struct sock *sk, long timeout) /* Forcefully remove dangling Phonet pipe */ pipe_do_remove(sk); -#ifdef CONFIG_PHONET_PIPECTRLR - if (pn->pipe_state != PIPE_IDLE) { - /* send pep disconnect request */ - pipe_handler_send_req(sk, - PNS_PEP_DISCONNECT_UTID, PNS_PEP_DISCONNECT_REQ, - GFP_KERNEL); - - pn->pipe_state = PIPE_IDLE; - sk->sk_state = TCP_CLOSE; - } -#endif - ifindex = pn->ifindex; pn->ifindex = 0; release_sock(sk); @@ -1038,20 +1108,6 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp) return newsk; } -#ifdef CONFIG_PHONET_PIPECTRLR -static int pep_sock_connect(struct sock *sk, struct sockaddr *addr, int len) -{ - struct pep_sock *pn = pep_sk(sk); - struct sockaddr_pn *spn = (struct sockaddr_pn *)addr; - - memcpy(&pn->remote_pep, spn, sizeof(struct sockaddr_pn)); - - return pipe_handler_send_req(sk, - PNS_PEP_CONNECT_UTID, PNS_PEP_CONNECT_REQ, - GFP_ATOMIC); -} -#endif - static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) { struct pep_sock *pn = pep_sk(sk); @@ -1093,6 +1149,10 @@ static int pep_setsockopt(struct sock *sk, int level, int optname, { struct pep_sock *pn = pep_sk(sk); int val = 0, err = 0; +#ifdef CONFIG_PHONET_PIPECTRLR + int remote_pep; + int pipe_handle; +#endif if (level != SOL_PNPIPE) return -ENOPROTOOPT; @@ -1104,15 +1164,28 @@ static int pep_setsockopt(struct sock *sk, int level, int optname, lock_sock(sk); switch (optname) { #ifdef CONFIG_PHONET_PIPECTRLR - case PNPIPE_PIPE_HANDLE: + case PNPIPE_CREATE: if (val) { if (pn->pipe_state > PIPE_IDLE) { err = -EFAULT; break; } - pn->pipe_handle = val; + remote_pep = val & 0xFFFF; + pipe_handle = (val >> 16) & 0xFF; + pn->remote_pep = remote_pep; + err = pipe_handler_create_pipe(sk, pipe_handle, + PNPIPE_CREATE); + break; + } + + case PNPIPE_DESTROY: + if (pn->pipe_state < PIPE_DISABLED) { + err = -EFAULT; break; } + + err = pipe_handler_create_pipe(sk, 0x0, PNPIPE_DESTROY); + break; #endif case PNPIPE_ENCAP: @@ -1205,6 +1278,14 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb) struct pep_sock *pn = pep_sk(sk); struct pnpipehdr *ph; int err; +#ifdef CONFIG_PHONET_PIPECTRLR + struct sockaddr_pn spn = { + .spn_family = AF_PHONET, + .spn_resource = 0xD9, + .spn_dev = pn_dev(pn->remote_pep), + .spn_obj = pn_obj(pn->remote_pep), + }; +#endif if (pn_flow_safe(pn->tx_fc) && !atomic_add_unless(&pn->tx_credits, -1, 0)) { @@ -1223,7 +1304,7 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb) ph->message_id = PNS_PIPE_DATA; ph->pipe_handle = pn->pipe_handle; #ifdef CONFIG_PHONET_PIPECTRLR - err = pn_skb_send(sk, skb, &pn->remote_pep); + err = pn_skb_send(sk, skb, &spn); #else err = pn_skb_send(sk, skb, &pipe_srv); #endif @@ -1423,8 +1504,6 @@ static void pep_sock_unhash(struct sock *sk) struct sock *skparent = NULL; lock_sock(sk); - -#ifndef CONFIG_PHONET_PIPECTRLR if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) { skparent = pn->listener; release_sock(sk); @@ -1434,7 +1513,6 @@ static void pep_sock_unhash(struct sock *sk) sk_del_node_init(sk); sk = skparent; } -#endif /* Unhash a listening sock only when it is closed * and all of its active connected pipes are closed. */ if (hlist_empty(&pn->hlist)) @@ -1448,9 +1526,6 @@ static void pep_sock_unhash(struct sock *sk) static struct proto pep_proto = { .close = pep_sock_close, .accept = pep_sock_accept, -#ifdef CONFIG_PHONET_PIPECTRLR - .connect = pep_sock_connect, -#endif .ioctl = pep_ioctl, .init = pep_init, .setsockopt = pep_setsockopt, diff --git a/trunk/net/phonet/socket.c b/trunk/net/phonet/socket.c index 25f746d20c1f..aca8fba099e9 100644 --- a/trunk/net/phonet/socket.c +++ b/trunk/net/phonet/socket.c @@ -225,101 +225,6 @@ static int pn_socket_autobind(struct socket *sock) return 0; /* socket was already bound */ } -#ifdef CONFIG_PHONET_PIPECTRLR -static int pn_socket_connect(struct socket *sock, struct sockaddr *addr, - int len, int flags) -{ - struct sock *sk = sock->sk; - struct sockaddr_pn *spn = (struct sockaddr_pn *)addr; - long timeo; - int err; - - if (len < sizeof(struct sockaddr_pn)) - return -EINVAL; - if (spn->spn_family != AF_PHONET) - return -EAFNOSUPPORT; - - lock_sock(sk); - - switch (sock->state) { - case SS_UNCONNECTED: - sk->sk_state = TCP_CLOSE; - break; - case SS_CONNECTING: - switch (sk->sk_state) { - case TCP_SYN_RECV: - sock->state = SS_CONNECTED; - err = -EISCONN; - goto out; - case TCP_CLOSE: - err = -EALREADY; - if (flags & O_NONBLOCK) - goto out; - goto wait_connect; - } - break; - case SS_CONNECTED: - switch (sk->sk_state) { - case TCP_SYN_RECV: - err = -EISCONN; - goto out; - case TCP_CLOSE: - sock->state = SS_UNCONNECTED; - break; - } - break; - case SS_DISCONNECTING: - case SS_FREE: - break; - } - sk->sk_state = TCP_CLOSE; - sk_stream_kill_queues(sk); - - sock->state = SS_CONNECTING; - err = sk->sk_prot->connect(sk, addr, len); - if (err < 0) { - sock->state = SS_UNCONNECTED; - sk->sk_state = TCP_CLOSE; - goto out; - } - - err = -EINPROGRESS; -wait_connect: - if (sk->sk_state != TCP_SYN_RECV && (flags & O_NONBLOCK)) - goto out; - - timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); - release_sock(sk); - - err = -ERESTARTSYS; - timeo = wait_event_interruptible_timeout(*sk_sleep(sk), - sk->sk_state != TCP_CLOSE, - timeo); - - lock_sock(sk); - if (timeo < 0) - goto out; /* -ERESTARTSYS */ - - err = -ETIMEDOUT; - if (timeo == 0 && sk->sk_state != TCP_SYN_RECV) - goto out; - - if (sk->sk_state != TCP_SYN_RECV) { - sock->state = SS_UNCONNECTED; - err = sock_error(sk); - if (!err) - err = -ECONNREFUSED; - goto out; - } - sock->state = SS_CONNECTED; - err = 0; - -out: - release_sock(sk); - return err; -} -#endif - static int pn_socket_accept(struct socket *sock, struct socket *newsock, int flags) { @@ -488,11 +393,7 @@ const struct proto_ops phonet_stream_ops = { .owner = THIS_MODULE, .release = pn_socket_release, .bind = pn_socket_bind, -#ifdef CONFIG_PHONET_PIPECTRLR - .connect = pn_socket_connect, -#else .connect = sock_no_connect, -#endif .socketpair = sock_no_socketpair, .accept = pn_socket_accept, .getname = pn_socket_getname, diff --git a/trunk/net/tipc/addr.c b/trunk/net/tipc/addr.c index 8a2e89bffde5..2ddc351b3be9 100644 --- a/trunk/net/tipc/addr.c +++ b/trunk/net/tipc/addr.c @@ -41,6 +41,11 @@ #include "cluster.h" #include "net.h" +u32 tipc_get_addr(void) +{ + return tipc_own_addr; +} + /** * tipc_addr_domain_valid - validates a network domain address * diff --git a/trunk/net/tipc/bcast.c b/trunk/net/tipc/bcast.c index 22a60fc98392..ecfaac10d0b4 100644 --- a/trunk/net/tipc/bcast.c +++ b/trunk/net/tipc/bcast.c @@ -121,9 +121,6 @@ static DEFINE_SPINLOCK(bc_lock); const char tipc_bclink_name[] = "broadcast-link"; -static void tipc_nmap_diff(struct tipc_node_map *nm_a, - struct tipc_node_map *nm_b, - struct tipc_node_map *nm_diff); static u32 buf_seqno(struct sk_buff *buf) { @@ -290,7 +287,7 @@ static void bclink_send_nack(struct tipc_node *n_ptr) if (!less(n_ptr->bclink.gap_after, n_ptr->bclink.gap_to)) return; - buf = tipc_buf_acquire(INT_H_SIZE); + buf = buf_acquire(INT_H_SIZE); if (buf) { msg = buf_msg(buf); tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, @@ -874,9 +871,8 @@ void tipc_nmap_remove(struct tipc_node_map *nm_ptr, u32 node) * @nm_diff: output node map A-B (i.e. nodes of A that are not in B) */ -static void tipc_nmap_diff(struct tipc_node_map *nm_a, - struct tipc_node_map *nm_b, - struct tipc_node_map *nm_diff) +void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b, + struct tipc_node_map *nm_diff) { int stop = ARRAY_SIZE(nm_a->map); int w; diff --git a/trunk/net/tipc/bcast.h b/trunk/net/tipc/bcast.h index 011c03f0a4ab..e8c2b81658c7 100644 --- a/trunk/net/tipc/bcast.h +++ b/trunk/net/tipc/bcast.h @@ -84,6 +84,9 @@ static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, struct tipc_node_m return !memcmp(nm_a, nm_b, sizeof(*nm_a)); } +void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b, + struct tipc_node_map *nm_diff); + void tipc_port_list_add(struct port_list *pl_ptr, u32 port); void tipc_port_list_free(struct port_list *pl_ptr); diff --git a/trunk/net/tipc/bearer.c b/trunk/net/tipc/bearer.c index fd9c06c68281..9c10c6b7c12b 100644 --- a/trunk/net/tipc/bearer.c +++ b/trunk/net/tipc/bearer.c @@ -288,6 +288,9 @@ static struct bearer *bearer_find(const char *name) struct bearer *b_ptr; u32 i; + if (tipc_mode != TIPC_NET_MODE) + return NULL; + for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) { if (b_ptr->active && (!strcmp(b_ptr->publ.name, name))) return b_ptr; @@ -627,17 +630,30 @@ int tipc_block_bearer(const char *name) * Note: This routine assumes caller holds tipc_net_lock. */ -static int bearer_disable(struct bearer *b_ptr) +static int bearer_disable(const char *name) { + struct bearer *b_ptr; struct link *l_ptr; struct link *temp_l_ptr; - info("Disabling bearer <%s>\n", b_ptr->publ.name); + b_ptr = bearer_find(name); + if (!b_ptr) { + warn("Attempt to disable unknown bearer <%s>\n", name); + return -EINVAL; + } + + info("Disabling bearer <%s>\n", name); tipc_disc_stop_link_req(b_ptr->link_req); spin_lock_bh(&b_ptr->publ.lock); b_ptr->link_req = NULL; b_ptr->publ.blocked = 1; - b_ptr->media->disable_bearer(&b_ptr->publ); + if (b_ptr->media->disable_bearer) { + spin_unlock_bh(&b_ptr->publ.lock); + write_unlock_bh(&tipc_net_lock); + b_ptr->media->disable_bearer(&b_ptr->publ); + write_lock_bh(&tipc_net_lock); + spin_lock_bh(&b_ptr->publ.lock); + } list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { tipc_link_delete(l_ptr); } @@ -648,16 +664,10 @@ static int bearer_disable(struct bearer *b_ptr) int tipc_disable_bearer(const char *name) { - struct bearer *b_ptr; int res; write_lock_bh(&tipc_net_lock); - b_ptr = bearer_find(name); - if (b_ptr == NULL) { - warn("Attempt to disable unknown bearer <%s>\n", name); - res = -EINVAL; - } else - res = bearer_disable(b_ptr); + res = bearer_disable(name); write_unlock_bh(&tipc_net_lock); return res; } @@ -670,7 +680,13 @@ void tipc_bearer_stop(void) for (i = 0; i < MAX_BEARERS; i++) { if (tipc_bearers[i].active) - bearer_disable(&tipc_bearers[i]); + tipc_bearers[i].publ.blocked = 1; + } + for (i = 0; i < MAX_BEARERS; i++) { + if (tipc_bearers[i].active) + bearer_disable(tipc_bearers[i].publ.name); } media_count = 0; } + + diff --git a/trunk/net/tipc/cluster.c b/trunk/net/tipc/cluster.c index 7fea14b98b97..e68f705381bc 100644 --- a/trunk/net/tipc/cluster.c +++ b/trunk/net/tipc/cluster.c @@ -113,6 +113,25 @@ void tipc_cltr_delete(struct cluster *c_ptr) kfree(c_ptr); } +u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr) +{ + struct tipc_node *n_ptr; + u32 n_num = tipc_node(addr) + 1; + + if (!c_ptr) + return addr; + for (; n_num <= c_ptr->highest_node; n_num++) { + n_ptr = c_ptr->nodes[n_num]; + if (n_ptr && tipc_node_has_active_links(n_ptr)) + return n_ptr->addr; + } + for (n_num = 1; n_num < tipc_node(addr); n_num++) { + n_ptr = c_ptr->nodes[n_num]; + if (n_ptr && tipc_node_has_active_links(n_ptr)) + return n_ptr->addr; + } + return 0; +} void tipc_cltr_attach_node(struct cluster *c_ptr, struct tipc_node *n_ptr) { @@ -213,7 +232,7 @@ struct tipc_node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector) static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest) { u32 size = INT_H_SIZE + data_size; - struct sk_buff *buf = tipc_buf_acquire(size); + struct sk_buff *buf = buf_acquire(size); struct tipc_msg *msg; if (buf) { diff --git a/trunk/net/tipc/cluster.h b/trunk/net/tipc/cluster.h index 32636d98c9c6..333efb0b9c44 100644 --- a/trunk/net/tipc/cluster.h +++ b/trunk/net/tipc/cluster.h @@ -75,7 +75,7 @@ void tipc_cltr_attach_node(struct cluster *c_ptr, struct tipc_node *n_ptr); void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest); void tipc_cltr_broadcast(struct sk_buff *buf); int tipc_cltr_init(void); - +u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr); void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest); void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); diff --git a/trunk/net/tipc/config.c b/trunk/net/tipc/config.c index 50a6133a3668..961d1b097146 100644 --- a/trunk/net/tipc/config.c +++ b/trunk/net/tipc/config.c @@ -95,7 +95,7 @@ int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, return 1; } -static struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value) +struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value) { struct sk_buff *buf; __be32 value_net; @@ -109,11 +109,6 @@ static struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value) return buf; } -static struct sk_buff *tipc_cfg_reply_unsigned(u32 value) -{ - return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value); -} - struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) { struct sk_buff *buf; @@ -125,6 +120,139 @@ struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) return buf; } + +#if 0 + +/* Now obsolete code for handling commands not yet implemented the new way */ + +/* + * Some of this code assumed that the manager structure contains two added + * fields: + * u32 link_subscriptions; + * struct list_head link_subscribers; + * which are currently not present. These fields may need to be re-introduced + * if and when support for link subscriptions is added. + */ + +void tipc_cfg_link_event(u32 addr, char *name, int up) +{ + /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */ +} + +int tipc_cfg_cmd(const struct tipc_cmd_msg * msg, + char *data, + u32 sz, + u32 *ret_size, + struct tipc_portid *orig) +{ + int rv = -EINVAL; + u32 cmd = msg->cmd; + + *ret_size = 0; + switch (cmd) { + case TIPC_REMOVE_LINK: + case TIPC_CMD_BLOCK_LINK: + case TIPC_CMD_UNBLOCK_LINK: + if (!cfg_check_connection(orig)) + rv = link_control(msg->argv.link_name, msg->cmd, 0); + break; + case TIPC_ESTABLISH: + { + int connected; + + tipc_isconnected(mng.conn_port_ref, &connected); + if (connected || !orig) { + rv = TIPC_FAILURE; + break; + } + rv = tipc_connect2port(mng.conn_port_ref, orig); + if (rv == TIPC_OK) + orig = 0; + break; + } + case TIPC_GET_PEER_ADDRESS: + *ret_size = link_peer_addr(msg->argv.link_name, data, sz); + break; + case TIPC_GET_ROUTES: + rv = TIPC_OK; + break; + default: {} + } + if (*ret_size) + rv = TIPC_OK; + return rv; +} + +static void cfg_cmd_event(struct tipc_cmd_msg *msg, + char *data, + u32 sz, + struct tipc_portid const *orig) +{ + int rv = -EINVAL; + struct tipc_cmd_result_msg rmsg; + struct iovec msg_sect[2]; + int *arg; + + msg->cmd = ntohl(msg->cmd); + + cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect, + data, 0); + if (ntohl(msg->magic) != TIPC_MAGIC) + goto exit; + + switch (msg->cmd) { + case TIPC_CREATE_LINK: + if (!cfg_check_connection(orig)) + rv = disc_create_link(&msg->argv.create_link); + break; + case TIPC_LINK_SUBSCRIBE: + { + struct subscr_data *sub; + + if (mng.link_subscriptions > 64) + break; + sub = kmalloc(sizeof(*sub), + GFP_ATOMIC); + if (sub == NULL) { + warn("Memory squeeze; dropped remote link subscription\n"); + break; + } + INIT_LIST_HEAD(&sub->subd_list); + tipc_createport(mng.user_ref, + (void *)sub, + TIPC_HIGH_IMPORTANCE, + 0, + 0, + (tipc_conn_shutdown_event)cfg_linksubscr_cancel, + 0, + 0, + (tipc_conn_msg_event)cfg_linksubscr_cancel, + 0, + &sub->port_ref); + if (!sub->port_ref) { + kfree(sub); + break; + } + memcpy(sub->usr_handle,msg->usr_handle, + sizeof(sub->usr_handle)); + sub->domain = msg->argv.domain; + list_add_tail(&sub->subd_list, &mng.link_subscribers); + tipc_connect2port(sub->port_ref, orig); + rmsg.retval = TIPC_OK; + tipc_send(sub->port_ref, 2u, msg_sect); + mng.link_subscriptions++; + return; + } + default: + rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig); + } +exit: + rmsg.result_len = htonl(msg_sect[1].iov_len); + rmsg.retval = htonl(rv); + tipc_cfg_respond(msg_sect, 2u, orig); +} +#endif + #define MAX_STATS_INFO 2000 static struct sk_buff *tipc_show_stats(void) @@ -429,6 +557,14 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area case TIPC_CMD_SHOW_PORTS: rep_tlv_buf = tipc_port_get_ports(); break; +#if 0 + case TIPC_CMD_SHOW_PORT_STATS: + rep_tlv_buf = port_show_stats(req_tlv_area, req_tlv_space); + break; + case TIPC_CMD_RESET_PORT_STATS: + rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED); + break; +#endif case TIPC_CMD_SET_LOG_SIZE: rep_tlv_buf = tipc_log_resize_cmd(req_tlv_area, req_tlv_space); break; diff --git a/trunk/net/tipc/config.h b/trunk/net/tipc/config.h index 481e12ece715..5cd7cc56c54d 100644 --- a/trunk/net/tipc/config.h +++ b/trunk/net/tipc/config.h @@ -45,6 +45,7 @@ struct sk_buff *tipc_cfg_reply_alloc(int payload_size); int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, void *tlv_data, int tlv_data_size); +struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value); struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string); static inline struct sk_buff *tipc_cfg_reply_none(void) @@ -52,6 +53,11 @@ static inline struct sk_buff *tipc_cfg_reply_none(void) return tipc_cfg_reply_alloc(0); } +static inline struct sk_buff *tipc_cfg_reply_unsigned(u32 value) +{ + return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value); +} + static inline struct sk_buff *tipc_cfg_reply_error_string(char *string) { return tipc_cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string); diff --git a/trunk/net/tipc/core.c b/trunk/net/tipc/core.c index e2a09eb8efd4..466b861dab91 100644 --- a/trunk/net/tipc/core.c +++ b/trunk/net/tipc/core.c @@ -96,8 +96,13 @@ int tipc_net_id; int tipc_remote_management; +int tipc_get_mode(void) +{ + return tipc_mode; +} + /** - * tipc_buf_acquire - creates a TIPC message buffer + * buf_acquire - creates a TIPC message buffer * @size: message size (including TIPC header) * * Returns a new buffer with data pointers set to the specified size. @@ -106,7 +111,7 @@ int tipc_remote_management; * There may also be unrequested tailroom present at the buffer's end. */ -struct sk_buff *tipc_buf_acquire(u32 size) +struct sk_buff *buf_acquire(u32 size) { struct sk_buff *skb; unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; @@ -124,7 +129,7 @@ struct sk_buff *tipc_buf_acquire(u32 size) * tipc_core_stop_net - shut down TIPC networking sub-systems */ -static void tipc_core_stop_net(void) +void tipc_core_stop_net(void) { tipc_eth_media_stop(); tipc_net_stop(); @@ -149,7 +154,7 @@ int tipc_core_start_net(unsigned long addr) * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode */ -static void tipc_core_stop(void) +void tipc_core_stop(void) { if (tipc_mode != TIPC_NODE_MODE) return; @@ -171,7 +176,7 @@ static void tipc_core_stop(void) * tipc_core_start - switch TIPC from NOT RUNNING to SINGLE NODE mode */ -static int tipc_core_start(void) +int tipc_core_start(void) { int res; @@ -241,6 +246,8 @@ MODULE_VERSION(TIPC_MOD_VER); EXPORT_SYMBOL(tipc_attach); EXPORT_SYMBOL(tipc_detach); +EXPORT_SYMBOL(tipc_get_addr); +EXPORT_SYMBOL(tipc_get_mode); EXPORT_SYMBOL(tipc_createport); EXPORT_SYMBOL(tipc_deleteport); EXPORT_SYMBOL(tipc_ownidentity); @@ -255,10 +262,23 @@ EXPORT_SYMBOL(tipc_withdraw); EXPORT_SYMBOL(tipc_connect2port); EXPORT_SYMBOL(tipc_disconnect); EXPORT_SYMBOL(tipc_shutdown); +EXPORT_SYMBOL(tipc_isconnected); +EXPORT_SYMBOL(tipc_peer); +EXPORT_SYMBOL(tipc_ref_valid); EXPORT_SYMBOL(tipc_send); +EXPORT_SYMBOL(tipc_send_buf); EXPORT_SYMBOL(tipc_send2name); +EXPORT_SYMBOL(tipc_forward2name); +EXPORT_SYMBOL(tipc_send_buf2name); +EXPORT_SYMBOL(tipc_forward_buf2name); EXPORT_SYMBOL(tipc_send2port); +EXPORT_SYMBOL(tipc_forward2port); +EXPORT_SYMBOL(tipc_send_buf2port); +EXPORT_SYMBOL(tipc_forward_buf2port); EXPORT_SYMBOL(tipc_multicast); +/* EXPORT_SYMBOL(tipc_multicast_buf); not available yet */ +EXPORT_SYMBOL(tipc_ispublished); +EXPORT_SYMBOL(tipc_available_nodes); /* TIPC API for external bearers (see tipc_bearer.h) */ @@ -275,4 +295,6 @@ EXPORT_SYMBOL(tipc_createport_raw); EXPORT_SYMBOL(tipc_reject_msg); EXPORT_SYMBOL(tipc_send_buf_fast); EXPORT_SYMBOL(tipc_acknowledge); +EXPORT_SYMBOL(tipc_get_port); +EXPORT_SYMBOL(tipc_get_handle); diff --git a/trunk/net/tipc/core.h b/trunk/net/tipc/core.h index e19389e57227..188799017abd 100644 --- a/trunk/net/tipc/core.h +++ b/trunk/net/tipc/core.h @@ -83,7 +83,9 @@ * Note: TIPC_LOG is configured to echo its output to the system console; * user-defined buffers can be configured to do the same thing. */ + extern struct print_buf *const TIPC_NULL; +extern struct print_buf *const TIPC_CONS; extern struct print_buf *const TIPC_LOG; void tipc_printf(struct print_buf *, const char *fmt, ...); @@ -202,7 +204,10 @@ extern atomic_t tipc_user_count; * Routines available to privileged subsystems */ -extern int tipc_core_start_net(unsigned long); +extern int tipc_core_start(void); +extern void tipc_core_stop(void); +extern int tipc_core_start_net(unsigned long addr); +extern void tipc_core_stop_net(void); extern int tipc_handler_start(void); extern void tipc_handler_stop(void); extern int tipc_netlink_start(void); @@ -323,7 +328,7 @@ static inline struct tipc_msg *buf_msg(struct sk_buff *skb) return (struct tipc_msg *)skb->data; } -extern struct sk_buff *tipc_buf_acquire(u32 size); +extern struct sk_buff *buf_acquire(u32 size); /** * buf_discard - frees a TIPC message buffer diff --git a/trunk/net/tipc/dbg.c b/trunk/net/tipc/dbg.c index 46f51d208e5e..6569d45bfb9a 100644 --- a/trunk/net/tipc/dbg.c +++ b/trunk/net/tipc/dbg.c @@ -52,7 +52,7 @@ static struct print_buf null_buf = { NULL, 0, NULL, 0 }; struct print_buf *const TIPC_NULL = &null_buf; static struct print_buf cons_buf = { NULL, 0, NULL, 1 }; -static struct print_buf *const TIPC_CONS = &cons_buf; +struct print_buf *const TIPC_CONS = &cons_buf; static struct print_buf log_buf = { NULL, 0, NULL, 1 }; struct print_buf *const TIPC_LOG = &log_buf; @@ -76,10 +76,6 @@ struct print_buf *const TIPC_LOG = &log_buf; static char print_string[TIPC_PB_MAX_STR]; static DEFINE_SPINLOCK(print_lock); -static void tipc_printbuf_reset(struct print_buf *pb); -static int tipc_printbuf_empty(struct print_buf *pb); -static void tipc_printbuf_move(struct print_buf *pb_to, - struct print_buf *pb_from); #define FORMAT(PTR,LEN,FMT) \ {\ @@ -120,7 +116,7 @@ void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size) * @pb: pointer to print buffer structure */ -static void tipc_printbuf_reset(struct print_buf *pb) +void tipc_printbuf_reset(struct print_buf *pb) { if (pb->buf) { pb->crs = pb->buf; @@ -136,7 +132,7 @@ static void tipc_printbuf_reset(struct print_buf *pb) * Returns non-zero if print buffer is empty. */ -static int tipc_printbuf_empty(struct print_buf *pb) +int tipc_printbuf_empty(struct print_buf *pb) { return !pb->buf || (pb->crs == pb->buf); } @@ -185,8 +181,7 @@ int tipc_printbuf_validate(struct print_buf *pb) * Source print buffer becomes empty if a successful move occurs. */ -static void tipc_printbuf_move(struct print_buf *pb_to, - struct print_buf *pb_from) +void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) { int len; diff --git a/trunk/net/tipc/dbg.h b/trunk/net/tipc/dbg.h index 3ba6ba8b434a..5ef1bc8f64ef 100644 --- a/trunk/net/tipc/dbg.h +++ b/trunk/net/tipc/dbg.h @@ -56,7 +56,10 @@ struct print_buf { #define TIPC_PB_MAX_STR 512 /* max printable string (with trailing NUL) */ void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 size); +void tipc_printbuf_reset(struct print_buf *pb); +int tipc_printbuf_empty(struct print_buf *pb); int tipc_printbuf_validate(struct print_buf *pb); +void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from); int tipc_log_resize(int log_size); diff --git a/trunk/net/tipc/discover.c b/trunk/net/tipc/discover.c index 4a7cd3719b78..f28d1ae93125 100644 --- a/trunk/net/tipc/discover.c +++ b/trunk/net/tipc/discover.c @@ -46,6 +46,16 @@ #define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */ #define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */ +#if 0 +#define GET_NODE_INFO 300 +#define GET_NODE_INFO_RESULT 301 +#define FORWARD_LINK_PROBE 302 +#define LINK_REQUEST_REJECTED 303 +#define LINK_REQUEST_ACCEPTED 304 +#define DROP_LINK_REQUEST 305 +#define CHECK_LINK_COUNT 306 +#endif + /* * TODO: Most of the inter-cluster setup stuff should be * rewritten, and be made conformant with specification. @@ -68,6 +78,30 @@ struct link_req { unsigned int timer_intv; }; + +#if 0 +int disc_create_link(const struct tipc_link_create *argv) +{ + /* + * Code for inter cluster link setup here + */ + return TIPC_OK; +} +#endif + +/* + * disc_lost_link(): A link has lost contact + */ + +void tipc_disc_link_event(u32 addr, char *name, int up) +{ + if (in_own_cluster(addr)) + return; + /* + * Code for inter cluster link setup here + */ +} + /** * tipc_disc_init_msg - initialize a link setup message * @type: message type (request or response) @@ -81,7 +115,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type, u32 dest_domain, struct bearer *b_ptr) { - struct sk_buff *buf = tipc_buf_acquire(DSC_H_SIZE); + struct sk_buff *buf = buf_acquire(DSC_H_SIZE); struct tipc_msg *msg; if (buf) { diff --git a/trunk/net/tipc/discover.h b/trunk/net/tipc/discover.h index f8e750636123..c36eaeb7d5d0 100644 --- a/trunk/net/tipc/discover.h +++ b/trunk/net/tipc/discover.h @@ -50,4 +50,9 @@ void tipc_disc_stop_link_req(struct link_req *req); void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr); +void tipc_disc_link_event(u32 addr, char *name, int up); +#if 0 +int disc_create_link(const struct tipc_link_create *argv); +#endif + #endif diff --git a/trunk/net/tipc/link.c b/trunk/net/tipc/link.c index b31992ccd5d3..b8cf1e9d0b86 100644 --- a/trunk/net/tipc/link.c +++ b/trunk/net/tipc/link.c @@ -99,6 +99,23 @@ struct link_name { char if_peer[TIPC_MAX_IF_NAME]; }; +#if 0 + +/* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */ + +/** + * struct link_event - link up/down event notification + */ + +struct link_event { + u32 addr; + int up; + void (*fcn)(u32, char *, int); + char name[TIPC_MAX_LINK_NAME]; +}; + +#endif + static void link_handle_out_of_seq_msg(struct link *l_ptr, struct sk_buff *buf); static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf); @@ -112,9 +129,6 @@ static void link_state_event(struct link *l_ptr, u32 event); static void link_reset_statistics(struct link *l_ptr); static void link_print(struct link *l_ptr, struct print_buf *buf, const char *str); -static void link_start(struct link *l_ptr); -static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf); - /* * Debugging code used by link routines only @@ -445,7 +459,7 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr); list_add_tail(&l_ptr->link_list, &b_ptr->links); - tipc_k_signal((Handler)link_start, (unsigned long)l_ptr); + tipc_k_signal((Handler)tipc_link_start, (unsigned long)l_ptr); dbg("tipc_link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n", l_ptr->tolerance, l_ptr->continuity_interval, l_ptr->abort_limit); @@ -485,9 +499,9 @@ void tipc_link_delete(struct link *l_ptr) kfree(l_ptr); } -static void link_start(struct link *l_ptr) +void tipc_link_start(struct link *l_ptr) { - dbg("link_start %x\n", l_ptr); + dbg("tipc_link_start %x\n", l_ptr); link_state_event(l_ptr, STARTING_EVT); } @@ -620,9 +634,39 @@ void tipc_link_stop(struct link *l_ptr) l_ptr->proto_msg_queue = NULL; } +#if 0 + /* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */ + +static void link_recv_event(struct link_event *ev) +{ + ev->fcn(ev->addr, ev->name, ev->up); + kfree(ev); +} + +static void link_send_event(void (*fcn)(u32 a, char *n, int up), + struct link *l_ptr, int up) +{ + struct link_event *ev; + + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + warn("Link event allocation failure\n"); + return; + } + ev->addr = l_ptr->addr; + ev->up = up; + ev->fcn = fcn; + memcpy(ev->name, l_ptr->name, TIPC_MAX_LINK_NAME); + tipc_k_signal((Handler)link_recv_event, (unsigned long)ev); +} + +#else + #define link_send_event(fcn, l_ptr, up) do { } while (0) +#endif + void tipc_link_reset(struct link *l_ptr) { struct sk_buff *buf; @@ -646,7 +690,10 @@ void tipc_link_reset(struct link *l_ptr) tipc_node_link_down(l_ptr->owner, l_ptr); tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr); - +#if 0 + tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name); + dbg_link_dump(); +#endif if (was_active_link && tipc_node_has_active_links(l_ptr->owner) && l_ptr->owner->permit_changeover) { l_ptr->reset_checkpoint = checkpoint; @@ -1003,7 +1050,7 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) /* Fragmentation needed ? */ if (size > max_packet) - return link_send_long_buf(l_ptr, buf); + return tipc_link_send_long_buf(l_ptr, buf); /* Packet can be queued or sent: */ @@ -1039,7 +1086,7 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) /* Try creating a new bundle */ if (size <= max_packet * 2 / 3) { - struct sk_buff *bundler = tipc_buf_acquire(max_packet); + struct sk_buff *bundler = buf_acquire(max_packet); struct tipc_msg bundler_hdr; if (bundler) { @@ -1315,7 +1362,7 @@ static int link_send_sections_long(struct port *sender, /* Prepare header of first fragment: */ - buf_chain = buf = tipc_buf_acquire(max_pkt); + buf_chain = buf = buf_acquire(max_pkt); if (!buf) return -ENOMEM; buf->next = NULL; @@ -1372,7 +1419,7 @@ static int link_send_sections_long(struct port *sender, msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); msg_set_fragm_no(&fragm_hdr, ++fragm_no); prev = buf; - buf = tipc_buf_acquire(fragm_sz + INT_H_SIZE); + buf = buf_acquire(fragm_sz + INT_H_SIZE); if (!buf) goto error; @@ -2148,7 +2195,7 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { if (!l_ptr->proto_msg_queue) { l_ptr->proto_msg_queue = - tipc_buf_acquire(sizeof(l_ptr->proto_msg)); + buf_acquire(sizeof(l_ptr->proto_msg)); } buf = l_ptr->proto_msg_queue; if (!buf) @@ -2162,7 +2209,7 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, msg_dbg(msg, ">>"); - buf = tipc_buf_acquire(msg_size); + buf = buf_acquire(msg_size); if (!buf) return; @@ -2321,10 +2368,10 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) * tipc_link_tunnel(): Send one message via a link belonging to * another bearer. Owner node is locked. */ -static void tipc_link_tunnel(struct link *l_ptr, - struct tipc_msg *tunnel_hdr, - struct tipc_msg *msg, - u32 selector) +void tipc_link_tunnel(struct link *l_ptr, + struct tipc_msg *tunnel_hdr, + struct tipc_msg *msg, + u32 selector) { struct link *tunnel; struct sk_buff *buf; @@ -2337,7 +2384,7 @@ static void tipc_link_tunnel(struct link *l_ptr, return; } msg_set_size(tunnel_hdr, length + INT_H_SIZE); - buf = tipc_buf_acquire(length + INT_H_SIZE); + buf = buf_acquire(length + INT_H_SIZE); if (!buf) { warn("Link changeover error, " "unable to send tunnel msg\n"); @@ -2383,7 +2430,7 @@ void tipc_link_changeover(struct link *l_ptr) if (!l_ptr->first_out) { struct sk_buff *buf; - buf = tipc_buf_acquire(INT_H_SIZE); + buf = buf_acquire(INT_H_SIZE); if (buf) { skb_copy_to_linear_data(buf, &tunnel_hdr, INT_H_SIZE); msg_set_size(&tunnel_hdr, INT_H_SIZE); @@ -2444,7 +2491,7 @@ void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel) msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); /* Update */ msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); msg_set_size(&tunnel_hdr, length + INT_H_SIZE); - outbuf = tipc_buf_acquire(length + INT_H_SIZE); + outbuf = buf_acquire(length + INT_H_SIZE); if (outbuf == NULL) { warn("Link changeover error, " "unable to send duplicate msg\n"); @@ -2480,7 +2527,7 @@ static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos) u32 size = msg_size(msg); struct sk_buff *eb; - eb = tipc_buf_acquire(size); + eb = buf_acquire(size); if (eb) skb_copy_to_linear_data(eb, msg, size); return eb; @@ -2608,11 +2655,11 @@ void tipc_link_recv_bundle(struct sk_buff *buf) /* - * link_send_long_buf: Entry for buffers needing fragmentation. + * tipc_link_send_long_buf: Entry for buffers needing fragmentation. * The buffer is complete, inclusive total message length. * Returns user data length. */ -static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) +int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) { struct tipc_msg *inmsg = buf_msg(buf); struct tipc_msg fragm_hdr; @@ -2651,7 +2698,7 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) fragm_sz = rest; msg_set_type(&fragm_hdr, LAST_FRAGMENT); } - fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE); + fragm = buf_acquire(fragm_sz + INT_H_SIZE); if (fragm == NULL) { warn("Link unable to fragment message\n"); dsz = -ENOMEM; @@ -2756,7 +2803,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, buf_discard(fbuf); return 0; } - pbuf = tipc_buf_acquire(msg_size(imsg)); + pbuf = buf_acquire(msg_size(imsg)); if (pbuf != NULL) { pbuf->next = *pending; *pending = pbuf; @@ -3150,6 +3197,44 @@ struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_s return buf; } +#if 0 +int link_control(const char *name, u32 op, u32 val) +{ + int res = -EINVAL; + struct link *l_ptr; + u32 bearer_id; + struct tipc_node * node; + u32 a; + + a = link_name2addr(name, &bearer_id); + read_lock_bh(&tipc_net_lock); + node = tipc_node_find(a); + if (node) { + tipc_node_lock(node); + l_ptr = node->links[bearer_id]; + if (l_ptr) { + if (op == TIPC_REMOVE_LINK) { + struct bearer *b_ptr = l_ptr->b_ptr; + spin_lock_bh(&b_ptr->publ.lock); + tipc_link_delete(l_ptr); + spin_unlock_bh(&b_ptr->publ.lock); + } + if (op == TIPC_CMD_BLOCK_LINK) { + tipc_link_reset(l_ptr); + l_ptr->blocked = 1; + } + if (op == TIPC_CMD_UNBLOCK_LINK) { + l_ptr->blocked = 0; + } + res = 0; + } + tipc_node_unlock(node); + } + read_unlock_bh(&tipc_net_lock); + return res; +} +#endif + /** * tipc_link_get_max_pkt - get maximum packet size to use when sending to destination * @dest: network address of destination node @@ -3180,6 +3265,28 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector) return res; } +#if 0 +static void link_dump_rec_queue(struct link *l_ptr) +{ + struct sk_buff *crs; + + if (!l_ptr->oldest_deferred_in) { + info("Reception queue empty\n"); + return; + } + info("Contents of Reception queue:\n"); + crs = l_ptr->oldest_deferred_in; + while (crs) { + if (crs->data == (void *)0x0000a3a3) { + info("buffer %x invalid\n", crs); + return; + } + msg_dbg(buf_msg(crs), "In rec queue:\n"); + crs = crs->next; + } +} +#endif + static void link_dump_send_queue(struct link *l_ptr) { if (l_ptr->next_out) { diff --git a/trunk/net/tipc/link.h b/trunk/net/tipc/link.h index f98bc613de67..26151d30589d 100644 --- a/trunk/net/tipc/link.h +++ b/trunk/net/tipc/link.h @@ -210,6 +210,10 @@ struct link { u32 msg_length_counts; u32 msg_lengths_total; u32 msg_length_profile[7]; +#if 0 + u32 sent_tunneled; + u32 recv_tunneled; +#endif } stats; struct print_buf print_buf; @@ -225,6 +229,7 @@ void tipc_link_send_duplicate(struct link *l_ptr, struct link *dest); void tipc_link_reset_fragments(struct link *l_ptr); int tipc_link_is_up(struct link *l_ptr); int tipc_link_is_active(struct link *l_ptr); +void tipc_link_start(struct link *l_ptr); u32 tipc_link_push_packet(struct link *l_ptr); void tipc_link_stop(struct link *l_ptr); struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd); @@ -238,6 +243,9 @@ int tipc_link_send_sections_fast(struct port* sender, struct iovec const *msg_sect, const u32 num_sect, u32 destnode); +int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf); +void tipc_link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr, + struct tipc_msg *msg, u32 selector); void tipc_link_recv_bundle(struct sk_buff *buf); int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, diff --git a/trunk/net/tipc/msg.c b/trunk/net/tipc/msg.c index ecb532fb0351..381063817b41 100644 --- a/trunk/net/tipc/msg.c +++ b/trunk/net/tipc/msg.c @@ -112,7 +112,7 @@ int tipc_msg_build(struct tipc_msg *hdr, return dsz; } - *buf = tipc_buf_acquire(sz); + *buf = buf_acquire(sz); if (!(*buf)) return -ENOMEM; skb_copy_to_linear_data(*buf, hdr, hsz); diff --git a/trunk/net/tipc/name_distr.c b/trunk/net/tipc/name_distr.c index 7b907171f879..6ac3c543250b 100644 --- a/trunk/net/tipc/name_distr.c +++ b/trunk/net/tipc/name_distr.c @@ -98,7 +98,7 @@ static void publ_to_item(struct distr_item *i, struct publication *p) static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) { - struct sk_buff *buf = tipc_buf_acquire(LONG_H_SIZE + size); + struct sk_buff *buf = buf_acquire(LONG_H_SIZE + size); struct tipc_msg *msg; if (buf != NULL) { diff --git a/trunk/net/tipc/name_table.c b/trunk/net/tipc/name_table.c index 3a8de4334da1..9ca4b0689237 100644 --- a/trunk/net/tipc/name_table.c +++ b/trunk/net/tipc/name_table.c @@ -1009,6 +1009,16 @@ static void nametbl_list(struct print_buf *buf, u32 depth_info, } } +#if 0 +void tipc_nametbl_print(struct print_buf *buf, const char *str) +{ + tipc_printf(buf, str); + read_lock_bh(&tipc_nametbl_lock); + nametbl_list(buf, 0, 0, 0, 0); + read_unlock_bh(&tipc_nametbl_lock); +} +#endif + #define MAX_NAME_TBL_QUERY 32768 struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space) @@ -1041,6 +1051,13 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space) return buf; } +#if 0 +void tipc_nametbl_dump(void) +{ + nametbl_list(TIPC_CONS, 0, 0, 0, 0); +} +#endif + int tipc_nametbl_init(void) { table.types = kcalloc(tipc_nametbl_size, sizeof(struct hlist_head), diff --git a/trunk/net/tipc/net.c b/trunk/net/tipc/net.c index 1a621cfd6604..7e05af47a196 100644 --- a/trunk/net/tipc/net.c +++ b/trunk/net/tipc/net.c @@ -129,6 +129,15 @@ u32 tipc_net_select_router(u32 addr, u32 ref) return tipc_zone_select_router(tipc_net.zones[tipc_zone(addr)], addr, ref); } +#if 0 +u32 tipc_net_next_node(u32 a) +{ + if (tipc_net.zones[tipc_zone(a)]) + return tipc_zone_next_node(a); + return 0; +} +#endif + void tipc_net_remove_as_router(u32 router) { u32 z_num; diff --git a/trunk/net/tipc/node.c b/trunk/net/tipc/node.c index b4d87eb2dc5d..7c49cd056df7 100644 --- a/trunk/net/tipc/node.c +++ b/trunk/net/tipc/node.c @@ -50,8 +50,7 @@ void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str); static void node_lost_contact(struct tipc_node *n_ptr); static void node_established_contact(struct tipc_node *n_ptr); -/* sorted list of nodes within cluster */ -static struct tipc_node *tipc_nodes = NULL; +struct tipc_node *tipc_nodes = NULL; /* sorted list of nodes within cluster */ static DEFINE_SPINLOCK(node_create_lock); @@ -126,6 +125,16 @@ void tipc_node_delete(struct tipc_node *n_ptr) if (!n_ptr) return; +#if 0 + /* Not needed because links are already deleted via tipc_bearer_stop() */ + + u32 l_num; + + for (l_num = 0; l_num < MAX_BEARERS; l_num++) { + link_delete(n_ptr->links[l_num]); + } +#endif + dbg("node %x deleted\n", n_ptr->addr); kfree(n_ptr); } @@ -588,6 +597,38 @@ void tipc_node_remove_router(struct tipc_node *n_ptr, u32 router) node_lost_contact(n_ptr); } +#if 0 +void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str) +{ + u32 i; + + tipc_printf(buf, "\n\n%s", str); + for (i = 0; i < MAX_BEARERS; i++) { + if (!n_ptr->links[i]) + continue; + tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]); + } + tipc_printf(buf, "Active links: [%x,%x]\n", + n_ptr->active_links[0], n_ptr->active_links[1]); +} +#endif + +u32 tipc_available_nodes(const u32 domain) +{ + struct tipc_node *n_ptr; + u32 cnt = 0; + + read_lock_bh(&tipc_net_lock); + for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { + if (!tipc_in_scope(domain, n_ptr->addr)) + continue; + if (tipc_node_is_up(n_ptr)) + cnt++; + } + read_unlock_bh(&tipc_net_lock); + return cnt; +} + struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) { u32 domain; diff --git a/trunk/net/tipc/node.h b/trunk/net/tipc/node.h index fff331b2d26c..45f3db3a595d 100644 --- a/trunk/net/tipc/node.h +++ b/trunk/net/tipc/node.h @@ -96,6 +96,7 @@ struct tipc_node { } bclink; }; +extern struct tipc_node *tipc_nodes; extern u32 tipc_own_tag; struct tipc_node *tipc_node_create(u32 addr); diff --git a/trunk/net/tipc/port.c b/trunk/net/tipc/port.c index 82092eaa1536..d760336f2ca8 100644 --- a/trunk/net/tipc/port.c +++ b/trunk/net/tipc/port.c @@ -293,6 +293,34 @@ int tipc_deleteport(u32 ref) return 0; } +/** + * tipc_get_port() - return port associated with 'ref' + * + * Note: Port is not locked. + */ + +struct tipc_port *tipc_get_port(const u32 ref) +{ + return (struct tipc_port *)tipc_ref_deref(ref); +} + +/** + * tipc_get_handle - return user handle associated to port 'ref' + */ + +void *tipc_get_handle(const u32 ref) +{ + struct port *p_ptr; + void * handle; + + p_ptr = tipc_port_lock(ref); + if (!p_ptr) + return NULL; + handle = p_ptr->publ.usr_handle; + tipc_port_unlock(p_ptr); + return handle; +} + static int port_unreliable(struct port *p_ptr) { return msg_src_droppable(&p_ptr->publ.phdr); @@ -364,7 +392,7 @@ static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, struct sk_buff *buf; struct tipc_msg *msg; - buf = tipc_buf_acquire(LONG_H_SIZE); + buf = buf_acquire(LONG_H_SIZE); if (buf) { msg = buf_msg(buf); tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode); @@ -405,7 +433,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) hdr_sz = MCAST_H_SIZE; else hdr_sz = LONG_H_SIZE; - rbuf = tipc_buf_acquire(data_sz + hdr_sz); + rbuf = buf_acquire(data_sz + hdr_sz); if (rbuf == NULL) { buf_discard(buf); return data_sz; @@ -682,6 +710,50 @@ struct sk_buff *tipc_port_get_ports(void) return buf; } +#if 0 + +#define MAX_PORT_STATS 2000 + +struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space) +{ + u32 ref; + struct port *p_ptr; + struct sk_buff *buf; + struct tlv_desc *rep_tlv; + struct print_buf pb; + int str_len; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_PORT_REF)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + ref = *(u32 *)TLV_DATA(req_tlv_area); + ref = ntohl(ref); + + p_ptr = tipc_port_lock(ref); + if (!p_ptr) + return cfg_reply_error_string("port not found"); + + buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_STATS)); + if (!buf) { + tipc_port_unlock(p_ptr); + return NULL; + } + rep_tlv = (struct tlv_desc *)buf->data; + + tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_STATS); + port_print(p_ptr, &pb, 1); + /* NEED TO FILL IN ADDITIONAL PORT STATISTICS HERE */ + tipc_port_unlock(p_ptr); + str_len = tipc_printbuf_validate(&pb); + + skb_put(buf, TLV_SPACE(str_len)); + TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); + + return buf; +} + +#endif + void tipc_port_reinit(void) { struct port *p_ptr; @@ -1214,13 +1286,50 @@ int tipc_shutdown(u32 ref) return tipc_disconnect(ref); } +int tipc_isconnected(u32 ref, int *isconnected) +{ + struct port *p_ptr; + + p_ptr = tipc_port_lock(ref); + if (!p_ptr) + return -EINVAL; + *isconnected = p_ptr->publ.connected; + tipc_port_unlock(p_ptr); + return 0; +} + +int tipc_peer(u32 ref, struct tipc_portid *peer) +{ + struct port *p_ptr; + int res; + + p_ptr = tipc_port_lock(ref); + if (!p_ptr) + return -EINVAL; + if (p_ptr->publ.connected) { + peer->ref = port_peerport(p_ptr); + peer->node = port_peernode(p_ptr); + res = 0; + } else + res = -ENOTCONN; + tipc_port_unlock(p_ptr); + return res; +} + +int tipc_ref_valid(u32 ref) +{ + /* Works irrespective of type */ + return !!tipc_ref_deref(ref); +} + + /* * tipc_port_recv_sections(): Concatenate and deliver sectioned * message for this node. */ -static int tipc_port_recv_sections(struct port *sender, unsigned int num_sect, - struct iovec const *msg_sect) +int tipc_port_recv_sections(struct port *sender, unsigned int num_sect, + struct iovec const *msg_sect) { struct sk_buff *buf; int res; @@ -1270,17 +1379,66 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) return -ELINKCONG; } +/** + * tipc_send_buf - send message buffer on connection + */ + +int tipc_send_buf(u32 ref, struct sk_buff *buf, unsigned int dsz) +{ + struct port *p_ptr; + struct tipc_msg *msg; + u32 destnode; + u32 hsz; + u32 sz; + u32 res; + + p_ptr = tipc_port_deref(ref); + if (!p_ptr || !p_ptr->publ.connected) + return -EINVAL; + + msg = &p_ptr->publ.phdr; + hsz = msg_hdr_sz(msg); + sz = hsz + dsz; + msg_set_size(msg, sz); + if (skb_cow(buf, hsz)) + return -ENOMEM; + + skb_push(buf, hsz); + skb_copy_to_linear_data(buf, msg, hsz); + destnode = msg_destnode(msg); + p_ptr->publ.congested = 1; + if (!tipc_port_congested(p_ptr)) { + if (likely(destnode != tipc_own_addr)) + res = tipc_send_buf_fast(buf, destnode); + else { + tipc_port_recv_msg(buf); + res = sz; + } + if (likely(res != -ELINKCONG)) { + port_incr_out_seqno(p_ptr); + p_ptr->sent++; + p_ptr->publ.congested = 0; + return res; + } + } + if (port_unreliable(p_ptr)) { + p_ptr->publ.congested = 0; + return dsz; + } + return -ELINKCONG; +} + /** * tipc_forward2name - forward message sections to port name */ -static int tipc_forward2name(u32 ref, - struct tipc_name const *name, - u32 domain, - u32 num_sect, - struct iovec const *msg_sect, - struct tipc_portid const *orig, - unsigned int importance) +int tipc_forward2name(u32 ref, + struct tipc_name const *name, + u32 domain, + u32 num_sect, + struct iovec const *msg_sect, + struct tipc_portid const *orig, + unsigned int importance) { struct port *p_ptr; struct tipc_msg *msg; @@ -1342,16 +1500,90 @@ int tipc_send2name(u32 ref, TIPC_PORT_IMPORTANCE); } +/** + * tipc_forward_buf2name - forward message buffer to port name + */ + +int tipc_forward_buf2name(u32 ref, + struct tipc_name const *name, + u32 domain, + struct sk_buff *buf, + unsigned int dsz, + struct tipc_portid const *orig, + unsigned int importance) +{ + struct port *p_ptr; + struct tipc_msg *msg; + u32 destnode = domain; + u32 destport; + int res; + + p_ptr = (struct port *)tipc_ref_deref(ref); + if (!p_ptr || p_ptr->publ.connected) + return -EINVAL; + + msg = &p_ptr->publ.phdr; + if (importance <= TIPC_CRITICAL_IMPORTANCE) + msg_set_importance(msg, importance); + msg_set_type(msg, TIPC_NAMED_MSG); + msg_set_orignode(msg, orig->node); + msg_set_origport(msg, orig->ref); + msg_set_nametype(msg, name->type); + msg_set_nameinst(msg, name->instance); + msg_set_lookup_scope(msg, tipc_addr_scope(domain)); + msg_set_hdr_sz(msg, LONG_H_SIZE); + msg_set_size(msg, LONG_H_SIZE + dsz); + destport = tipc_nametbl_translate(name->type, name->instance, &destnode); + msg_set_destnode(msg, destnode); + msg_set_destport(msg, destport); + msg_dbg(msg, "forw2name ==> "); + if (skb_cow(buf, LONG_H_SIZE)) + return -ENOMEM; + skb_push(buf, LONG_H_SIZE); + skb_copy_to_linear_data(buf, msg, LONG_H_SIZE); + msg_dbg(buf_msg(buf),"PREP:"); + if (likely(destport)) { + p_ptr->sent++; + if (destnode == tipc_own_addr) + return tipc_port_recv_msg(buf); + res = tipc_send_buf_fast(buf, destnode); + if (likely(res != -ELINKCONG)) + return res; + if (port_unreliable(p_ptr)) + return dsz; + return -ELINKCONG; + } + return tipc_reject_msg(buf, TIPC_ERR_NO_NAME); +} + +/** + * tipc_send_buf2name - send message buffer to port name + */ + +int tipc_send_buf2name(u32 ref, + struct tipc_name const *dest, + u32 domain, + struct sk_buff *buf, + unsigned int dsz) +{ + struct tipc_portid orig; + + orig.ref = ref; + orig.node = tipc_own_addr; + return tipc_forward_buf2name(ref, dest, domain, buf, dsz, &orig, + TIPC_PORT_IMPORTANCE); +} + /** * tipc_forward2port - forward message sections to port identity */ -static int tipc_forward2port(u32 ref, - struct tipc_portid const *dest, - unsigned int num_sect, - struct iovec const *msg_sect, - struct tipc_portid const *orig, - unsigned int importance) +int tipc_forward2port(u32 ref, + struct tipc_portid const *dest, + unsigned int num_sect, + struct iovec const *msg_sect, + struct tipc_portid const *orig, + unsigned int importance) { struct port *p_ptr; struct tipc_msg *msg; @@ -1403,12 +1635,12 @@ int tipc_send2port(u32 ref, /** * tipc_forward_buf2port - forward message buffer to port identity */ -static int tipc_forward_buf2port(u32 ref, - struct tipc_portid const *dest, - struct sk_buff *buf, - unsigned int dsz, - struct tipc_portid const *orig, - unsigned int importance) +int tipc_forward_buf2port(u32 ref, + struct tipc_portid const *dest, + struct sk_buff *buf, + unsigned int dsz, + struct tipc_portid const *orig, + unsigned int importance) { struct port *p_ptr; struct tipc_msg *msg; diff --git a/trunk/net/tipc/port.h b/trunk/net/tipc/port.h index 73bbf442b346..e74bd9563739 100644 --- a/trunk/net/tipc/port.h +++ b/trunk/net/tipc/port.h @@ -109,6 +109,8 @@ struct port { extern spinlock_t tipc_port_list_lock; struct port_list; +int tipc_port_recv_sections(struct port *p_ptr, u32 num_sect, + struct iovec const *msg_sect); int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, struct iovec const *msg_sect, u32 num_sect, int err); diff --git a/trunk/net/tipc/ref.c b/trunk/net/tipc/ref.c index ab8ad32d8c20..8dea66500cf5 100644 --- a/trunk/net/tipc/ref.c +++ b/trunk/net/tipc/ref.c @@ -282,6 +282,23 @@ void *tipc_ref_lock(u32 ref) return NULL; } +/** + * tipc_ref_unlock - unlock referenced object + */ + +void tipc_ref_unlock(u32 ref) +{ + if (likely(tipc_ref_table.entries)) { + struct reference *entry; + + entry = &tipc_ref_table.entries[ref & + tipc_ref_table.index_mask]; + if (likely((entry->ref == ref) && (entry->object))) + spin_unlock_bh(&entry->lock); + else + err("Attempt to unlock non-existent reference\n"); + } +} /** * tipc_ref_deref - return pointer referenced object (without locking it) diff --git a/trunk/net/tipc/ref.h b/trunk/net/tipc/ref.h index 5bc8e7ab84de..7e3798ea93b9 100644 --- a/trunk/net/tipc/ref.h +++ b/trunk/net/tipc/ref.h @@ -44,6 +44,7 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock); void tipc_ref_discard(u32 ref); void *tipc_ref_lock(u32 ref); +void tipc_ref_unlock(u32 ref); void *tipc_ref_deref(u32 ref); #endif diff --git a/trunk/net/tipc/subscr.c b/trunk/net/tipc/subscr.c index 18813acc6bef..1a5b9a6bd128 100644 --- a/trunk/net/tipc/subscr.c +++ b/trunk/net/tipc/subscr.c @@ -598,3 +598,12 @@ void tipc_subscr_stop(void) topsrv.user_ref = 0; } } + + +int tipc_ispublished(struct tipc_name const *name) +{ + u32 domain = 0; + + return tipc_nametbl_translate(name->type, name->instance, &domain) != 0; +} + diff --git a/trunk/net/tipc/zone.c b/trunk/net/tipc/zone.c index 83f8b5e91fc8..2c01ba2d86bf 100644 --- a/trunk/net/tipc/zone.c +++ b/trunk/net/tipc/zone.c @@ -160,3 +160,14 @@ u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref) } return 0; } + + +u32 tipc_zone_next_node(u32 addr) +{ + struct cluster *c_ptr = tipc_cltr_find(addr); + + if (c_ptr) + return tipc_cltr_next_node(c_ptr, addr); + return 0; +} + diff --git a/trunk/net/tipc/zone.h b/trunk/net/tipc/zone.h index bd1c20ce9d06..7bdc3406ba9b 100644 --- a/trunk/net/tipc/zone.h +++ b/trunk/net/tipc/zone.h @@ -61,6 +61,7 @@ void tipc_zone_send_external_routes(struct _zone *z_ptr, u32 dest); struct _zone *tipc_zone_create(u32 addr); void tipc_zone_delete(struct _zone *z_ptr); void tipc_zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr); +u32 tipc_zone_next_node(u32 addr); static inline struct _zone *tipc_zone_find(u32 addr) {