diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5116aec3c174..f184fb5bd110 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -411,9 +411,6 @@ config XEN_NETDEV_BACKEND config VMXNET3 tristate "VMware VMXNET3 ethernet driver" depends on PCI && INET - depends on !(PAGE_SIZE_64KB || ARM64_64K_PAGES || \ - IA64_PAGE_SIZE_64KB || MICROBLAZE_64K_PAGES || \ - PARISC_PAGE_SIZE_64KB || PPC_64K_PAGES) help This driver supports VMware's vmxnet3 virtual ethernet NIC. To compile this driver as a module, choose M here: the diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c index 2e4649655181..e90c6a7333d7 100644 --- a/drivers/net/appletalk/ipddp.c +++ b/drivers/net/appletalk/ipddp.c @@ -191,7 +191,7 @@ static netdev_tx_t ipddp_xmit(struct sk_buff *skb, struct net_device *dev) */ static int ipddp_create(struct ipddp_route *new_rt) { - struct ipddp_route *rt = kzalloc(sizeof(*rt), GFP_KERNEL); + struct ipddp_route *rt = kmalloc(sizeof(*rt), GFP_KERNEL); if (rt == NULL) return -ENOMEM; diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 82d23bd3a742..bb9e9fc45e1b 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -453,7 +453,7 @@ static void rlb_update_client(struct rlb_client_info *client_info) { int i; - if (!client_info->slave || !is_valid_ether_addr(client_info->mac_dst)) + if (!client_info->slave) return; for (i = 0; i < RLB_ARP_BURST_SIZE; i++) { diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 339118f3c718..b3d70a7a5262 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1317,10 +1317,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) slave_dev->name); } - /* already in-use? */ - if (netdev_is_rx_handler_busy(slave_dev)) { - netdev_err(bond_dev, - "Error: Device is in use and cannot be enslaved\n"); + /* already enslaved */ + if (slave_dev->flags & IFF_SLAVE) { + netdev_dbg(bond_dev, "Error: Device was already enslaved\n"); return -EBUSY; } @@ -1490,6 +1489,39 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_close; } + /* If the mode uses primary, then the following is handled by + * bond_change_active_slave(). + */ + if (!bond_uses_primary(bond)) { + /* set promiscuity level to new slave */ + if (bond_dev->flags & IFF_PROMISC) { + res = dev_set_promiscuity(slave_dev, 1); + if (res) + goto err_close; + } + + /* set allmulti level to new slave */ + if (bond_dev->flags & IFF_ALLMULTI) { + res = dev_set_allmulti(slave_dev, 1); + if (res) + goto err_close; + } + + netif_addr_lock_bh(bond_dev); + + dev_mc_sync_multiple(slave_dev, bond_dev); + dev_uc_sync_multiple(slave_dev, bond_dev); + + netif_addr_unlock_bh(bond_dev); + } + + if (BOND_MODE(bond) == BOND_MODE_8023AD) { + /* add lacpdu mc addr to mc list */ + u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; + + dev_mc_add(slave_dev, lacpdu_multicast); + } + res = vlan_vids_add_by_dev(slave_dev, bond_dev); if (res) { netdev_err(bond_dev, "Couldn't add bond vlan ids to %s\n", @@ -1614,7 +1646,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) } /* switch(bond_mode) */ #ifdef CONFIG_NET_POLL_CONTROLLER - if (bond->dev->npinfo) { + slave_dev->npinfo = bond->dev->npinfo; + if (slave_dev->npinfo) { if (slave_enable_netpoll(new_slave)) { netdev_info(bond_dev, "master_dev is using netpoll, but new slave device does not support netpoll\n"); res = -EBUSY; @@ -1645,40 +1678,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_upper_unlink; } - /* If the mode uses primary, then the following is handled by - * bond_change_active_slave(). - */ - if (!bond_uses_primary(bond)) { - /* set promiscuity level to new slave */ - if (bond_dev->flags & IFF_PROMISC) { - res = dev_set_promiscuity(slave_dev, 1); - if (res) - goto err_sysfs_del; - } - - /* set allmulti level to new slave */ - if (bond_dev->flags & IFF_ALLMULTI) { - res = dev_set_allmulti(slave_dev, 1); - if (res) { - if (bond_dev->flags & IFF_PROMISC) - dev_set_promiscuity(slave_dev, -1); - goto err_sysfs_del; - } - } - - netif_addr_lock_bh(bond_dev); - dev_mc_sync_multiple(slave_dev, bond_dev); - dev_uc_sync_multiple(slave_dev, bond_dev); - netif_addr_unlock_bh(bond_dev); - - if (BOND_MODE(bond) == BOND_MODE_8023AD) { - /* add lacpdu mc addr to mc list */ - u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; - - dev_mc_add(slave_dev, lacpdu_multicast); - } - } - bond->slave_cnt++; bond_compute_features(bond); bond_set_carrier(bond); @@ -1702,9 +1701,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) return 0; /* Undo stages on error */ -err_sysfs_del: - bond_sysfs_slave_del(new_slave); - err_upper_unlink: bond_upper_dev_unlink(bond_dev, slave_dev); @@ -1712,6 +1708,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) netdev_rx_handler_unregister(slave_dev); err_detach: + if (!bond_uses_primary(bond)) + bond_hw_addr_flush(bond_dev, slave_dev); + vlan_vids_del_by_dev(slave_dev, bond_dev); if (rcu_access_pointer(bond->primary_slave) == new_slave) RCU_INIT_POINTER(bond->primary_slave, NULL); @@ -2555,13 +2554,11 @@ static void bond_loadbalance_arp_mon(struct work_struct *work) bond_for_each_slave_rcu(bond, slave, iter) { unsigned long trans_start = dev_trans_start(slave->dev); - slave->new_link = BOND_LINK_NOCHANGE; - if (slave->link != BOND_LINK_UP) { if (bond_time_in_interval(bond, trans_start, 1) && bond_time_in_interval(bond, slave->last_rx, 1)) { - slave->new_link = BOND_LINK_UP; + slave->link = BOND_LINK_UP; slave_state_changed = 1; /* primary_slave has no meaning in round-robin @@ -2588,7 +2585,7 @@ static void bond_loadbalance_arp_mon(struct work_struct *work) if (!bond_time_in_interval(bond, trans_start, 2) || !bond_time_in_interval(bond, slave->last_rx, 2)) { - slave->new_link = BOND_LINK_DOWN; + slave->link = BOND_LINK_DOWN; slave_state_changed = 1; if (slave->link_failure_count < UINT_MAX) @@ -2619,11 +2616,6 @@ static void bond_loadbalance_arp_mon(struct work_struct *work) if (!rtnl_trylock()) goto re_arm; - bond_for_each_slave(bond, slave, iter) { - if (slave->new_link != BOND_LINK_NOCHANGE) - slave->link = slave->new_link; - } - if (slave_state_changed) { bond_slave_state_change(bond); if (BOND_MODE(bond) == BOND_MODE_XOR) @@ -3173,7 +3165,7 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb) hash ^= (hash >> 16); hash ^= (hash >> 8); - return hash >> 1; + return hash; } /*-------------------------- Device entry points ----------------------------*/ @@ -3283,17 +3275,12 @@ static void bond_fold_stats(struct rtnl_link_stats64 *_res, for (i = 0; i < sizeof(*_res) / sizeof(u64); i++) { u64 nv = new[i]; u64 ov = old[i]; - s64 delta = nv - ov; /* detects if this particular field is 32bit only */ if (((nv | ov) >> 32) == 0) - delta = (s64)(s32)((u32)nv - (u32)ov); - - /* filter anomalies, some drivers reset their stats - * at down/up events. - */ - if (delta > 0) - res[i] += delta; + res[i] += (u32)nv - (u32)ov; + else + res[i] += nv - ov; } } diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index b8df0f5e8c25..db760e84119f 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -446,11 +446,7 @@ static int bond_newlink(struct net *src_net, struct net_device *bond_dev, if (err < 0) return err; - err = register_netdevice(bond_dev); - - netif_carrier_off(bond_dev); - - return err; + return register_netdevice(bond_dev); } static size_t bond_get_size(const struct net_device *bond_dev) diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 66560a8fcfa2..55e93b6b6d21 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -1115,7 +1115,6 @@ static int bond_option_primary_set(struct bonding *bond, slave->dev->name); rcu_assign_pointer(bond->primary_slave, slave); strcpy(bond->params.primary, slave->dev->name); - bond->force_primary = true; bond_select_active_slave(bond); goto out; } diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 8f5e93cb7975..8b3275d7792a 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -712,10 +712,9 @@ static int at91_poll_rx(struct net_device *dev, int quota) /* upper group completed, look again in lower */ if (priv->rx_next > get_mb_rx_low_last(priv) && - mb > get_mb_rx_last(priv)) { + quota > 0 && mb > get_mb_rx_last(priv)) { priv->rx_next = get_mb_rx_first(priv); - if (quota > 0) - goto again; + goto again; } return received; diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index e3dccd3200d5..f91b094288da 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -332,23 +332,9 @@ static void c_can_setup_tx_object(struct net_device *dev, int iface, priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); - if (priv->type == BOSCH_D_CAN) { - u32 data = 0, dreg = C_CAN_IFACE(DATA1_REG, iface); - - for (i = 0; i < frame->can_dlc; i += 4, dreg += 2) { - data = (u32)frame->data[i]; - data |= (u32)frame->data[i + 1] << 8; - data |= (u32)frame->data[i + 2] << 16; - data |= (u32)frame->data[i + 3] << 24; - priv->write_reg32(priv, dreg, data); - } - } else { - for (i = 0; i < frame->can_dlc; i += 2) { - priv->write_reg(priv, - C_CAN_IFACE(DATA1_REG, iface) + i / 2, - frame->data[i] | - (frame->data[i + 1] << 8)); - } + for (i = 0; i < frame->can_dlc; i += 2) { + priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2, + frame->data[i] | (frame->data[i + 1] << 8)); } } @@ -416,20 +402,10 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl) } else { int i, dreg = C_CAN_IFACE(DATA1_REG, iface); - if (priv->type == BOSCH_D_CAN) { - for (i = 0; i < frame->can_dlc; i += 4, dreg += 2) { - data = priv->read_reg32(priv, dreg); - frame->data[i] = data; - frame->data[i + 1] = data >> 8; - frame->data[i + 2] = data >> 16; - frame->data[i + 3] = data >> 24; - } - } else { - for (i = 0; i < frame->can_dlc; i += 2, dreg++) { - data = priv->read_reg(priv, dreg); - frame->data[i] = data; - frame->data[i + 1] = data >> 8; - } + for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { + data = priv->read_reg(priv, dreg); + frame->data[i] = data; + frame->data[i + 1] = data >> 8; } } diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c index d065c0e2d18e..7be393c96b1a 100644 --- a/drivers/net/can/c_can/c_can_pci.c +++ b/drivers/net/can/c_can/c_can_pci.c @@ -161,7 +161,6 @@ static int c_can_pci_probe(struct pci_dev *pdev, dev->irq = pdev->irq; priv->base = addr; - priv->device = &pdev->dev; if (!c_can_pci_data->freq) { dev_err(&pdev->dev, "no clock frequency defined\n"); @@ -178,6 +177,7 @@ static int c_can_pci_probe(struct pci_dev *pdev, break; case BOSCH_D_CAN: priv->regs = reg_map_d_can; + priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; break; default: ret = -EINVAL; diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 717530eac70c..e36d10520e24 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -320,6 +320,7 @@ static int c_can_plat_probe(struct platform_device *pdev) break; case BOSCH_D_CAN: priv->regs = reg_map_d_can; + priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; priv->read_reg = c_can_plat_read_reg_aligned_to_16bit; priv->write_reg = c_can_plat_write_reg_aligned_to_16bit; priv->read_reg32 = d_can_plat_read_reg32; diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c index 6da69af103e6..1e37313054f3 100644 --- a/drivers/net/can/cc770/cc770.c +++ b/drivers/net/can/cc770/cc770.c @@ -390,23 +390,37 @@ static int cc770_get_berr_counter(const struct net_device *dev, return 0; } -static void cc770_tx(struct net_device *dev, int mo) +static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct cc770_priv *priv = netdev_priv(dev); - struct can_frame *cf = (struct can_frame *)priv->tx_skb->data; + struct net_device_stats *stats = &dev->stats; + struct can_frame *cf = (struct can_frame *)skb->data; + unsigned int mo = obj2msgobj(CC770_OBJ_TX); u8 dlc, rtr; u32 id; int i; + if (can_dropped_invalid_skb(dev, skb)) + return NETDEV_TX_OK; + + if ((cc770_read_reg(priv, + msgobj[mo].ctrl1) & TXRQST_UNC) == TXRQST_SET) { + netdev_err(dev, "TX register is still occupied!\n"); + return NETDEV_TX_BUSY; + } + + netif_stop_queue(dev); + dlc = cf->can_dlc; id = cf->can_id; - rtr = cf->can_id & CAN_RTR_FLAG ? 0 : MSGCFG_DIR; - - cc770_write_reg(priv, msgobj[mo].ctrl0, - MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES); + if (cf->can_id & CAN_RTR_FLAG) + rtr = 0; + else + rtr = MSGCFG_DIR; cc770_write_reg(priv, msgobj[mo].ctrl1, RMTPND_RES | TXRQST_RES | CPUUPD_SET | NEWDAT_RES); - + cc770_write_reg(priv, msgobj[mo].ctrl0, + MSGVAL_SET | TXIE_SET | RXIE_RES | INTPND_RES); if (id & CAN_EFF_FLAG) { id &= CAN_EFF_MASK; cc770_write_reg(priv, msgobj[mo].config, @@ -425,30 +439,22 @@ static void cc770_tx(struct net_device *dev, int mo) for (i = 0; i < dlc; i++) cc770_write_reg(priv, msgobj[mo].data[i], cf->data[i]); - cc770_write_reg(priv, msgobj[mo].ctrl1, - RMTPND_UNC | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC); - cc770_write_reg(priv, msgobj[mo].ctrl0, - MSGVAL_SET | TXIE_SET | RXIE_SET | INTPND_UNC); -} - -static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct cc770_priv *priv = netdev_priv(dev); - unsigned int mo = obj2msgobj(CC770_OBJ_TX); + /* Store echo skb before starting the transfer */ + can_put_echo_skb(skb, dev, 0); - if (can_dropped_invalid_skb(dev, skb)) - return NETDEV_TX_OK; + cc770_write_reg(priv, msgobj[mo].ctrl1, + RMTPND_RES | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC); - netif_stop_queue(dev); + stats->tx_bytes += dlc; - if ((cc770_read_reg(priv, - msgobj[mo].ctrl1) & TXRQST_UNC) == TXRQST_SET) { - netdev_err(dev, "TX register is still occupied!\n"); - return NETDEV_TX_BUSY; - } - priv->tx_skb = skb; - cc770_tx(dev, mo); + /* + * HM: We had some cases of repeated IRQs so make sure the + * INT is acknowledged I know it's already further up, but + * doing again fixed the issue + */ + cc770_write_reg(priv, msgobj[mo].ctrl0, + MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES); return NETDEV_TX_OK; } @@ -674,46 +680,19 @@ static void cc770_tx_interrupt(struct net_device *dev, unsigned int o) struct cc770_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; unsigned int mo = obj2msgobj(o); - struct can_frame *cf; - u8 ctrl1; - - ctrl1 = cc770_read_reg(priv, msgobj[mo].ctrl1); + /* Nothing more to send, switch off interrupts */ cc770_write_reg(priv, msgobj[mo].ctrl0, MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES); - cc770_write_reg(priv, msgobj[mo].ctrl1, - RMTPND_RES | TXRQST_RES | MSGLST_RES | NEWDAT_RES); - - if (unlikely(!priv->tx_skb)) { - netdev_err(dev, "missing tx skb in tx interrupt\n"); - return; - } - - if (unlikely(ctrl1 & MSGLST_SET)) { - stats->rx_over_errors++; - stats->rx_errors++; - } - - /* When the CC770 is sending an RTR message and it receives a regular - * message that matches the id of the RTR message, it will overwrite the - * outgoing message in the TX register. When this happens we must - * process the received message and try to transmit the outgoing skb - * again. + /* + * We had some cases of repeated IRQ so make sure the + * INT is acknowledged */ - if (unlikely(ctrl1 & NEWDAT_SET)) { - cc770_rx(dev, mo, ctrl1); - cc770_tx(dev, mo); - return; - } + cc770_write_reg(priv, msgobj[mo].ctrl0, + MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES); - cf = (struct can_frame *)priv->tx_skb->data; - stats->tx_bytes += cf->can_dlc; stats->tx_packets++; - - can_put_echo_skb(priv->tx_skb, dev, 0); can_get_echo_skb(dev, 0); - priv->tx_skb = NULL; - netif_wake_queue(dev); } @@ -825,7 +804,6 @@ struct net_device *alloc_cc770dev(int sizeof_priv) priv->can.do_set_bittiming = cc770_set_bittiming; priv->can.do_set_mode = cc770_set_mode; priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; - priv->tx_skb = NULL; memcpy(priv->obj_flags, cc770_obj_flags, sizeof(cc770_obj_flags)); diff --git a/drivers/net/can/cc770/cc770.h b/drivers/net/can/cc770/cc770.h index 95752e1d1283..a1739db98d91 100644 --- a/drivers/net/can/cc770/cc770.h +++ b/drivers/net/can/cc770/cc770.h @@ -193,8 +193,6 @@ struct cc770_priv { u8 cpu_interface; /* CPU interface register */ u8 clkout; /* Clock out register */ u8 bus_config; /* Bus conffiguration register */ - - struct sk_buff *tx_skb; }; struct net_device *alloc_cc770dev(int sizeof_priv); diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index eab132778e67..910c12e2638e 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -472,8 +471,9 @@ EXPORT_SYMBOL_GPL(can_free_echo_skb); /* * CAN device restart for bus-off recovery */ -static void can_restart(struct net_device *dev) +static void can_restart(unsigned long data) { + struct net_device *dev = (struct net_device *)data; struct can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct sk_buff *skb; @@ -513,14 +513,6 @@ static void can_restart(struct net_device *dev) netdev_err(dev, "Error %d during restart", err); } -static void can_restart_work(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct can_priv *priv = container_of(dwork, struct can_priv, restart_work); - - can_restart(priv->dev); -} - int can_restart_now(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); @@ -534,8 +526,8 @@ int can_restart_now(struct net_device *dev) if (priv->state != CAN_STATE_BUS_OFF) return -EBUSY; - cancel_delayed_work_sync(&priv->restart_work); - can_restart(dev); + /* Runs as soon as possible in the timer context */ + mod_timer(&priv->restart_timer, jiffies); return 0; } @@ -556,8 +548,8 @@ void can_bus_off(struct net_device *dev) netif_carrier_off(dev); if (priv->restart_ms) - schedule_delayed_work(&priv->restart_work, - msecs_to_jiffies(priv->restart_ms)); + mod_timer(&priv->restart_timer, + jiffies + (priv->restart_ms * HZ) / 1000); } EXPORT_SYMBOL_GPL(can_bus_off); @@ -666,7 +658,6 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max) return NULL; priv = netdev_priv(dev); - priv->dev = dev; if (echo_skb_max) { priv->echo_skb_max = echo_skb_max; @@ -676,7 +667,7 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max) priv->state = CAN_STATE_STOPPED; - INIT_DELAYED_WORK(&priv->restart_work, can_restart_work); + init_timer(&priv->restart_timer); return dev; } @@ -757,6 +748,8 @@ int open_candev(struct net_device *dev) if (!netif_carrier_ok(dev)) netif_carrier_on(dev); + setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev); + return 0; } EXPORT_SYMBOL_GPL(open_candev); @@ -771,7 +764,7 @@ void close_candev(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); - cancel_delayed_work_sync(&priv->restart_work); + del_timer_sync(&priv->restart_timer); can_flush_echo_skb(dev); } EXPORT_SYMBOL_GPL(close_candev); @@ -805,9 +798,6 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[]) * - control mode with CAN_CTRLMODE_FD set */ - if (!data) - return 0; - if (data[IFLA_CAN_CTRLMODE]) { struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]); @@ -1018,11 +1008,6 @@ static int can_newlink(struct net *src_net, struct net_device *dev, return -EOPNOTSUPP; } -static void can_dellink(struct net_device *dev, struct list_head *head) -{ - return; -} - static struct rtnl_link_ops can_link_ops __read_mostly = { .kind = "can", .maxtype = IFLA_CAN_MAX, @@ -1031,7 +1016,6 @@ static struct rtnl_link_ops can_link_ops __read_mostly = { .validate = can_validate, .newlink = can_newlink, .changelink = can_changelink, - .dellink = can_dellink, .get_size = can_get_size, .fill_info = can_fill_info, .get_xstats_size = can_get_xstats_size, diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 47f43bdecd51..41c0fc9f3b14 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -493,7 +493,7 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) data = be32_to_cpup((__be32 *)&cf->data[0]); flexcan_write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[0]); } - if (cf->can_dlc > 4) { + if (cf->can_dlc > 3) { data = be32_to_cpup((__be32 *)&cf->data[4]); flexcan_write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[1]); } @@ -1268,10 +1268,11 @@ static int __maybe_unused flexcan_suspend(struct device *device) struct flexcan_priv *priv = netdev_priv(dev); int err; + err = flexcan_chip_disable(priv); + if (err) + return err; + if (netif_running(dev)) { - err = flexcan_chip_disable(priv); - if (err) - return err; netif_stop_queue(dev); netif_device_detach(dev); } @@ -1284,17 +1285,13 @@ static int __maybe_unused flexcan_resume(struct device *device) { struct net_device *dev = dev_get_drvdata(device); struct flexcan_priv *priv = netdev_priv(dev); - int err; priv->can.state = CAN_STATE_ERROR_ACTIVE; if (netif_running(dev)) { netif_device_attach(dev); netif_start_queue(dev); - err = flexcan_chip_enable(priv); - if (err) - return err; } - return 0; + return flexcan_chip_enable(priv); } static SIMPLE_DEV_PM_OPS(flexcan_pm_ops, flexcan_suspend, flexcan_resume); diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 2949a381a94d..c7427bdd3a4b 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -86,11 +86,6 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev, return 0; } cdm = of_iomap(np_cdm, 0); - if (!cdm) { - of_node_put(np_cdm); - dev_err(&ofdev->dev, "can't map clock node!\n"); - return 0; - } if (in_8(&cdm->ipb_clk_sel) & 0x1) freq *= 2; diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 1ac2090a1721..68ef0a4cd821 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -342,7 +342,7 @@ static int sun4i_can_start(struct net_device *dev) /* enter the selected mode */ mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR); - if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) + if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK) mod_reg_val |= SUN4I_MSEL_LOOPBACK_MODE; else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) mod_reg_val |= SUN4I_MSEL_LISTEN_ONLY_MODE; @@ -539,13 +539,6 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status) } stats->rx_over_errors++; stats->rx_errors++; - - /* reset the CAN IP by entering reset mode - * ignoring timeout error - */ - set_reset_mode(dev); - set_normal_mode(dev); - /* clear bit */ sun4i_can_write_cmdreg(priv, SUN4I_CMD_CLEAR_OR_FLAG); } @@ -660,9 +653,8 @@ static irqreturn_t sun4i_can_interrupt(int irq, void *dev_id) netif_wake_queue(dev); can_led_event(dev, CAN_LED_EVENT_TX); } - if ((isrc & SUN4I_INT_RBUF_VLD) && - !(isrc & SUN4I_INT_DATA_OR)) { - /* receive interrupt - don't read if overrun occurred */ + if (isrc & SUN4I_INT_RBUF_VLD) { + /* receive interrupt */ while (status & SUN4I_STA_RBUF_RDY) { /* RX buffer is not empty */ sun4i_can_rx(dev); @@ -819,6 +811,7 @@ static int sun4ican_probe(struct platform_device *pdev) priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_PRESUME_ACK | CAN_CTRLMODE_3_SAMPLES; priv->base = addr; priv->clk = clk; diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 4d01d7bc24ef..680d1ff07a55 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -652,9 +652,6 @@ static int ti_hecc_rx_poll(struct napi_struct *napi, int quota) mbx_mask = hecc_read(priv, HECC_CANMIM); mbx_mask |= HECC_TX_MBOX_MASK; hecc_write(priv, HECC_CANMIM, mbx_mask); - } else { - /* repoll is done only if whole budget is used */ - num_pkts = quota; } return num_pkts; @@ -951,12 +948,7 @@ static int ti_hecc_probe(struct platform_device *pdev) netif_napi_add(ndev, &priv->napi, ti_hecc_rx_poll, HECC_DEF_NAPI_WEIGHT); - err = clk_prepare_enable(priv->clk); - if (err) { - dev_err(&pdev->dev, "clk_prepare_enable() failed\n"); - goto probe_exit_clk; - } - + clk_enable(priv->clk); err = register_candev(ndev); if (err) { dev_err(&pdev->dev, "register_candev() failed\n"); @@ -989,7 +981,7 @@ static int ti_hecc_remove(struct platform_device *pdev) struct ti_hecc_priv *priv = netdev_priv(ndev); unregister_candev(ndev); - clk_disable_unprepare(priv->clk); + clk_disable(priv->clk); clk_put(priv->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); iounmap(priv->base); @@ -1014,7 +1006,7 @@ static int ti_hecc_suspend(struct platform_device *pdev, pm_message_t state) hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_PDR); priv->can.state = CAN_STATE_SLEEPING; - clk_disable_unprepare(priv->clk); + clk_disable(priv->clk); return 0; } @@ -1023,11 +1015,8 @@ static int ti_hecc_resume(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct ti_hecc_priv *priv = netdev_priv(dev); - int err; - err = clk_prepare_enable(priv->clk); - if (err) - return err; + clk_enable(priv->clk); hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_PDR); priv->can.state = CAN_STATE_ERROR_ACTIVE; diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 047348033e27..eb7192fab593 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -290,8 +290,6 @@ static void ems_usb_read_interrupt_callback(struct urb *urb) case -ECONNRESET: /* unlink */ case -ENOENT: - case -EPIPE: - case -EPROTO: case -ESHUTDOWN: return; @@ -1078,7 +1076,6 @@ static void ems_usb_disconnect(struct usb_interface *intf) usb_free_urb(dev->intr_urb); kfree(dev->intr_in_buffer); - kfree(dev->tx_msg_buffer); } } diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index afa5b4a7a4a2..113e64fcd73b 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -333,7 +333,7 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv, } cf->can_id = id & ESD_IDMASK; - cf->can_dlc = get_can_dlc(msg->msg.rx.dlc & ~ESD_RTR); + cf->can_dlc = get_can_dlc(msg->msg.rx.dlc); if (id & ESD_EXTID) cf->can_id |= CAN_EFF_FLAG; @@ -393,8 +393,6 @@ static void esd_usb2_read_bulk_callback(struct urb *urb) break; case -ENOENT: - case -EPIPE: - case -EPROTO: case -ESHUTDOWN: return; diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index b227f81e4a7e..cbc99d5649af 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -246,8 +246,6 @@ static int gs_cmd_reset(struct gs_usb *gsusb, struct gs_can *gsdev) sizeof(*dm), 1000); - kfree(dm); - return rc; } @@ -356,8 +354,6 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) gs_free_tx_context(txc); - atomic_dec(&dev->active_tx_urbs); - netif_wake_queue(netdev); } @@ -430,7 +426,7 @@ static int gs_usb_set_bittiming(struct net_device *netdev) dev_err(netdev->dev.parent, "Couldn't set bittimings (err=%d)", rc); - return (rc > 0) ? 0 : rc; + return rc; } static void gs_usb_xmit_callback(struct urb *urb) @@ -446,6 +442,14 @@ static void gs_usb_xmit_callback(struct urb *urb) urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); + + atomic_dec(&dev->active_tx_urbs); + + if (!netif_device_present(netdev)) + return; + + if (netif_queue_stopped(netdev)) + netif_wake_queue(netdev); } static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, struct net_device *netdev) diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index 59f891bebcc6..022bfa13ebfa 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -134,7 +134,6 @@ static inline bool kvaser_is_usbcan(const struct usb_device_id *id) #define CMD_RESET_ERROR_COUNTER 49 #define CMD_TX_ACKNOWLEDGE 50 #define CMD_CAN_ERROR_EVENT 51 -#define CMD_FLUSH_QUEUE_REPLY 68 #define CMD_LEAF_USB_THROTTLE 77 #define CMD_LEAF_LOG_MESSAGE 106 @@ -603,8 +602,8 @@ static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id, } if (pos + tmp->len > actual_len) { - dev_err_ratelimited(dev->udev->dev.parent, - "Format error\n"); + dev_err(dev->udev->dev.parent, + "Format error\n"); break; } @@ -809,7 +808,6 @@ static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv, if (err) { netdev_err(netdev, "Error transmitting URB\n"); usb_unanchor_urb(urb); - kfree(buf); usb_free_urb(urb); return err; } @@ -1175,7 +1173,7 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev, skb = alloc_can_skb(priv->netdev, &cf); if (!skb) { - stats->rx_dropped++; + stats->tx_dropped++; return; } @@ -1299,11 +1297,6 @@ static void kvaser_usb_handle_message(const struct kvaser_usb *dev, goto warn; break; - case CMD_FLUSH_QUEUE_REPLY: - if (dev->family != KVASER_LEAF) - goto warn; - break; - default: warn: dev_warn(dev->udev->dev.parent, "Unhandled message (%d)\n", msg->id); @@ -1322,8 +1315,6 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb) case 0: break; case -ENOENT: - case -EPIPE: - case -EPROTO: case -ESHUTDOWN: return; default: @@ -1332,7 +1323,7 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb) goto resubmit_urb; } - while (pos <= (int)(urb->actual_length - MSG_HEADER_LEN)) { + while (pos <= urb->actual_length - MSG_HEADER_LEN) { msg = urb->transfer_buffer + pos; /* The Kvaser firmware can only read and write messages that @@ -1351,8 +1342,7 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb) } if (pos + msg->len > urb->actual_length) { - dev_err_ratelimited(dev->udev->dev.parent, - "Format error\n"); + dev_err(dev->udev->dev.parent, "Format error\n"); break; } @@ -1617,8 +1607,7 @@ static int kvaser_usb_close(struct net_device *netdev) if (err) netdev_warn(netdev, "Cannot flush queue, error %d\n", err); - err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel); - if (err) + if (kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel)) netdev_warn(netdev, "Cannot reset card, error %d\n", err); err = kvaser_usb_stop_chip(priv); @@ -1771,7 +1760,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, spin_unlock_irqrestore(&priv->tx_contexts_lock, flags); usb_unanchor_urb(urb); - kfree(buf); stats->tx_dropped++; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index 91be4575b524..5a2e341a6d1e 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -872,25 +872,23 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter, static void peak_usb_disconnect(struct usb_interface *intf) { struct peak_usb_device *dev; - struct peak_usb_device *dev_prev_siblings; /* unregister as many netdev devices as siblings */ - for (dev = usb_get_intfdata(intf); dev; dev = dev_prev_siblings) { + for (dev = usb_get_intfdata(intf); dev; dev = dev->prev_siblings) { struct net_device *netdev = dev->netdev; char name[IFNAMSIZ]; - dev_prev_siblings = dev->prev_siblings; dev->state &= ~PCAN_USB_STATE_CONNECTED; strncpy(name, netdev->name, IFNAMSIZ); unregister_netdev(netdev); + free_candev(netdev); kfree(dev->cmd_buf); dev->next_siblings = NULL; if (dev->adapter->dev_free) dev->adapter->dev_free(dev); - free_candev(netdev); dev_info(&intf->dev, "%s removed\n", name); } diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c index 64cc86a82b2d..ce44a033f63b 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c @@ -184,7 +184,7 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) void *cmd_head = pcan_usb_fd_cmd_buffer(dev); int err = 0; u8 *packet_ptr; - int packet_len; + int i, n = 1, packet_len; ptrdiff_t cmd_len; /* usb device unregistered? */ @@ -201,13 +201,17 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) } packet_ptr = cmd_head; - packet_len = cmd_len; /* firmware is not able to re-assemble 512 bytes buffer in full-speed */ - if (unlikely(dev->udev->speed != USB_SPEED_HIGH)) - packet_len = min(packet_len, PCAN_UFD_LOSPD_PKT_SIZE); + if ((dev->udev->speed != USB_SPEED_HIGH) && + (cmd_len > PCAN_UFD_LOSPD_PKT_SIZE)) { + packet_len = PCAN_UFD_LOSPD_PKT_SIZE; + n += cmd_len / packet_len; + } else { + packet_len = cmd_len; + } - do { + for (i = 0; i < n; i++) { err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, PCAN_USBPRO_EP_CMDOUT), @@ -220,12 +224,7 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) } packet_ptr += packet_len; - cmd_len -= packet_len; - - if (cmd_len < PCAN_UFD_LOSPD_PKT_SIZE) - packet_len = cmd_len; - - } while (packet_len > 0); + } return err; } diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c index 522286cc0f9c..a731720f1d13 100644 --- a/drivers/net/can/usb/usb_8dev.c +++ b/drivers/net/can/usb/usb_8dev.c @@ -524,8 +524,6 @@ static void usb_8dev_read_bulk_callback(struct urb *urb) break; case -ENOENT: - case -EPIPE: - case -EPROTO: case -ESHUTDOWN: return; @@ -956,8 +954,8 @@ static int usb_8dev_probe(struct usb_interface *intf, for (i = 0; i < MAX_TX_URBS; i++) priv->tx_contexts[i].echo_index = MAX_TX_URBS; - priv->cmd_msg_buffer = devm_kzalloc(&intf->dev, sizeof(struct usb_8dev_cmd_msg), - GFP_KERNEL); + priv->cmd_msg_buffer = kzalloc(sizeof(struct usb_8dev_cmd_msg), + GFP_KERNEL); if (!priv->cmd_msg_buffer) goto cleanup_candev; @@ -971,7 +969,7 @@ static int usb_8dev_probe(struct usb_interface *intf, if (err) { netdev_err(netdev, "couldn't register CAN device: %d\n", err); - goto cleanup_candev; + goto cleanup_cmd_msg_buffer; } err = usb_8dev_cmd_version(priv, &version); @@ -992,6 +990,9 @@ static int usb_8dev_probe(struct usb_interface *intf, cleanup_unregister_candev: unregister_netdev(priv->netdev); +cleanup_cmd_msg_buffer: + kfree(priv->cmd_msg_buffer); + cleanup_candev: free_candev(netdev); diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 700b98d9c250..51670b322409 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -2,7 +2,6 @@ * * Copyright (C) 2012 - 2014 Xilinx, Inc. * Copyright (C) 2009 PetaLogix. All rights reserved. - * Copyright (C) 2017 Sandvik Mining and Construction Oy * * Description: * This driver is developed for Axi CAN IP and for Zynq CANPS Controller. @@ -26,10 +25,8 @@ #include #include #include -#include #include #include -#include #include #include #include @@ -103,7 +100,7 @@ enum xcan_reg { #define XCAN_INTR_ALL (XCAN_IXR_TXOK_MASK | XCAN_IXR_BSOFF_MASK |\ XCAN_IXR_WKUP_MASK | XCAN_IXR_SLP_MASK | \ XCAN_IXR_RXNEMP_MASK | XCAN_IXR_ERROR_MASK | \ - XCAN_IXR_RXOFLW_MASK | XCAN_IXR_ARBLST_MASK) + XCAN_IXR_ARBLST_MASK | XCAN_IXR_RXOK_MASK) /* CAN register bit shift - XCAN___SHIFT */ #define XCAN_BTR_SJW_SHIFT 7 /* Synchronous jump width */ @@ -120,7 +117,6 @@ enum xcan_reg { /** * struct xcan_priv - This definition define CAN driver instance * @can: CAN private data structure. - * @tx_lock: Lock for synchronizing TX interrupt handling * @tx_head: Tx CAN packets ready to send on the queue * @tx_tail: Tx CAN packets successfully sended on the queue * @tx_max: Maximum number packets the driver can send @@ -135,7 +131,6 @@ enum xcan_reg { */ struct xcan_priv { struct can_priv can; - spinlock_t tx_lock; unsigned int tx_head; unsigned int tx_tail; unsigned int tx_max; @@ -163,11 +158,6 @@ static const struct can_bittiming_const xcan_bittiming_const = { .brp_inc = 1, }; -#define XCAN_CAP_WATERMARK 0x0001 -struct xcan_devtype_data { - unsigned int caps; -}; - /** * xcan_write_reg_le - Write a value to the device register little endian * @priv: Driver private data structure @@ -247,10 +237,6 @@ static int set_reset_mode(struct net_device *ndev) usleep_range(500, 10000); } - /* reset clears FIFOs */ - priv->tx_head = 0; - priv->tx_tail = 0; - return 0; } @@ -405,7 +391,6 @@ static int xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct net_device_stats *stats = &ndev->stats; struct can_frame *cf = (struct can_frame *)skb->data; u32 id, dlc, data[2] = {0, 0}; - unsigned long flags; if (can_dropped_invalid_skb(ndev, skb)) return NETDEV_TX_OK; @@ -453,9 +438,6 @@ static int xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev) data[1] = be32_to_cpup((__be32 *)(cf->data + 4)); can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max); - - spin_lock_irqsave(&priv->tx_lock, flags); - priv->tx_head++; /* Write the Frame to Xilinx CAN TX FIFO */ @@ -471,16 +453,10 @@ static int xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev) stats->tx_bytes += cf->can_dlc; } - /* Clear TX-FIFO-empty interrupt for xcan_tx_interrupt() */ - if (priv->tx_max > 1) - priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXFEMP_MASK); - /* Check if the TX buffer is full */ if ((priv->tx_head - priv->tx_tail) == priv->tx_max) netif_stop_queue(ndev); - spin_unlock_irqrestore(&priv->tx_lock, flags); - return NETDEV_TX_OK; } @@ -552,123 +528,6 @@ static int xcan_rx(struct net_device *ndev) return 1; } -/** - * xcan_current_error_state - Get current error state from HW - * @ndev: Pointer to net_device structure - * - * Checks the current CAN error state from the HW. Note that this - * only checks for ERROR_PASSIVE and ERROR_WARNING. - * - * Return: - * ERROR_PASSIVE or ERROR_WARNING if either is active, ERROR_ACTIVE - * otherwise. - */ -static enum can_state xcan_current_error_state(struct net_device *ndev) -{ - struct xcan_priv *priv = netdev_priv(ndev); - u32 status = priv->read_reg(priv, XCAN_SR_OFFSET); - - if ((status & XCAN_SR_ESTAT_MASK) == XCAN_SR_ESTAT_MASK) - return CAN_STATE_ERROR_PASSIVE; - else if (status & XCAN_SR_ERRWRN_MASK) - return CAN_STATE_ERROR_WARNING; - else - return CAN_STATE_ERROR_ACTIVE; -} - -/** - * xcan_set_error_state - Set new CAN error state - * @ndev: Pointer to net_device structure - * @new_state: The new CAN state to be set - * @cf: Error frame to be populated or NULL - * - * Set new CAN error state for the device, updating statistics and - * populating the error frame if given. - */ -static void xcan_set_error_state(struct net_device *ndev, - enum can_state new_state, - struct can_frame *cf) -{ - struct xcan_priv *priv = netdev_priv(ndev); - u32 ecr = priv->read_reg(priv, XCAN_ECR_OFFSET); - u32 txerr = ecr & XCAN_ECR_TEC_MASK; - u32 rxerr = (ecr & XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT; - - priv->can.state = new_state; - - if (cf) { - cf->can_id |= CAN_ERR_CRTL; - cf->data[6] = txerr; - cf->data[7] = rxerr; - } - - switch (new_state) { - case CAN_STATE_ERROR_PASSIVE: - priv->can.can_stats.error_passive++; - if (cf) - cf->data[1] = (rxerr > 127) ? - CAN_ERR_CRTL_RX_PASSIVE : - CAN_ERR_CRTL_TX_PASSIVE; - break; - case CAN_STATE_ERROR_WARNING: - priv->can.can_stats.error_warning++; - if (cf) - cf->data[1] |= (txerr > rxerr) ? - CAN_ERR_CRTL_TX_WARNING : - CAN_ERR_CRTL_RX_WARNING; - break; - case CAN_STATE_ERROR_ACTIVE: - if (cf) - cf->data[1] |= CAN_ERR_CRTL_ACTIVE; - break; - default: - /* non-ERROR states are handled elsewhere */ - WARN_ON(1); - break; - } -} - -/** - * xcan_update_error_state_after_rxtx - Update CAN error state after RX/TX - * @ndev: Pointer to net_device structure - * - * If the device is in a ERROR-WARNING or ERROR-PASSIVE state, check if - * the performed RX/TX has caused it to drop to a lesser state and set - * the interface state accordingly. - */ -static void xcan_update_error_state_after_rxtx(struct net_device *ndev) -{ - struct xcan_priv *priv = netdev_priv(ndev); - enum can_state old_state = priv->can.state; - enum can_state new_state; - - /* changing error state due to successful frame RX/TX can only - * occur from these states - */ - if (old_state != CAN_STATE_ERROR_WARNING && - old_state != CAN_STATE_ERROR_PASSIVE) - return; - - new_state = xcan_current_error_state(ndev); - - if (new_state != old_state) { - struct sk_buff *skb; - struct can_frame *cf; - - skb = alloc_can_err_skb(ndev, &cf); - - xcan_set_error_state(ndev, new_state, skb ? cf : NULL); - - if (skb) { - struct net_device_stats *stats = &ndev->stats; - - stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; - netif_rx(skb); - } - } -} - /** * xcan_err_interrupt - error frame Isr * @ndev: net_device pointer @@ -684,12 +543,16 @@ static void xcan_err_interrupt(struct net_device *ndev, u32 isr) struct net_device_stats *stats = &ndev->stats; struct can_frame *cf; struct sk_buff *skb; - u32 err_status; + u32 err_status, status, txerr = 0, rxerr = 0; skb = alloc_can_err_skb(ndev, &cf); err_status = priv->read_reg(priv, XCAN_ESR_OFFSET); priv->write_reg(priv, XCAN_ESR_OFFSET, err_status); + txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK; + rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) & + XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT); + status = priv->read_reg(priv, XCAN_SR_OFFSET); if (isr & XCAN_IXR_BSOFF_MASK) { priv->can.state = CAN_STATE_BUS_OFF; @@ -699,10 +562,28 @@ static void xcan_err_interrupt(struct net_device *ndev, u32 isr) can_bus_off(ndev); if (skb) cf->can_id |= CAN_ERR_BUSOFF; - } else { - enum can_state new_state = xcan_current_error_state(ndev); - - xcan_set_error_state(ndev, new_state, skb ? cf : NULL); + } else if ((status & XCAN_SR_ESTAT_MASK) == XCAN_SR_ESTAT_MASK) { + priv->can.state = CAN_STATE_ERROR_PASSIVE; + priv->can.can_stats.error_passive++; + if (skb) { + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] = (rxerr > 127) ? + CAN_ERR_CRTL_RX_PASSIVE : + CAN_ERR_CRTL_TX_PASSIVE; + cf->data[6] = txerr; + cf->data[7] = rxerr; + } + } else if (status & XCAN_SR_ERRWRN_MASK) { + priv->can.state = CAN_STATE_ERROR_WARNING; + priv->can.can_stats.error_warning++; + if (skb) { + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] |= (txerr > rxerr) ? + CAN_ERR_CRTL_TX_WARNING : + CAN_ERR_CRTL_RX_WARNING; + cf->data[6] = txerr; + cf->data[7] = rxerr; + } } /* Check for Arbitration lost interrupt */ @@ -718,6 +599,7 @@ static void xcan_err_interrupt(struct net_device *ndev, u32 isr) if (isr & XCAN_IXR_RXOFLW_MASK) { stats->rx_over_errors++; stats->rx_errors++; + priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); if (skb) { cf->can_id |= CAN_ERR_CRTL; cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; @@ -826,20 +708,26 @@ static int xcan_rx_poll(struct napi_struct *napi, int quota) isr = priv->read_reg(priv, XCAN_ISR_OFFSET); while ((isr & XCAN_IXR_RXNEMP_MASK) && (work_done < quota)) { - work_done += xcan_rx(ndev); + if (isr & XCAN_IXR_RXOK_MASK) { + priv->write_reg(priv, XCAN_ICR_OFFSET, + XCAN_IXR_RXOK_MASK); + work_done += xcan_rx(ndev); + } else { + priv->write_reg(priv, XCAN_ICR_OFFSET, + XCAN_IXR_RXNEMP_MASK); + break; + } priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_RXNEMP_MASK); isr = priv->read_reg(priv, XCAN_ISR_OFFSET); } - if (work_done) { + if (work_done) can_led_event(ndev, CAN_LED_EVENT_RX); - xcan_update_error_state_after_rxtx(ndev); - } if (work_done < quota) { napi_complete(napi); ier = priv->read_reg(priv, XCAN_IER_OFFSET); - ier |= XCAN_IXR_RXNEMP_MASK; + ier |= (XCAN_IXR_RXOK_MASK | XCAN_IXR_RXNEMP_MASK); priv->write_reg(priv, XCAN_IER_OFFSET, ier); } return work_done; @@ -854,71 +742,18 @@ static void xcan_tx_interrupt(struct net_device *ndev, u32 isr) { struct xcan_priv *priv = netdev_priv(ndev); struct net_device_stats *stats = &ndev->stats; - unsigned int frames_in_fifo; - int frames_sent = 1; /* TXOK => at least 1 frame was sent */ - unsigned long flags; - int retries = 0; - - /* Synchronize with xmit as we need to know the exact number - * of frames in the FIFO to stay in sync due to the TXFEMP - * handling. - * This also prevents a race between netif_wake_queue() and - * netif_stop_queue(). - */ - spin_lock_irqsave(&priv->tx_lock, flags); - frames_in_fifo = priv->tx_head - priv->tx_tail; - - if (WARN_ON_ONCE(frames_in_fifo == 0)) { - /* clear TXOK anyway to avoid getting back here */ + while ((priv->tx_head - priv->tx_tail > 0) && + (isr & XCAN_IXR_TXOK_MASK)) { priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK); - spin_unlock_irqrestore(&priv->tx_lock, flags); - return; - } - - /* Check if 2 frames were sent (TXOK only means that at least 1 - * frame was sent). - */ - if (frames_in_fifo > 1) { - WARN_ON(frames_in_fifo > priv->tx_max); - - /* Synchronize TXOK and isr so that after the loop: - * (1) isr variable is up-to-date at least up to TXOK clear - * time. This avoids us clearing a TXOK of a second frame - * but not noticing that the FIFO is now empty and thus - * marking only a single frame as sent. - * (2) No TXOK is left. Having one could mean leaving a - * stray TXOK as we might process the associated frame - * via TXFEMP handling as we read TXFEMP *after* TXOK - * clear to satisfy (1). - */ - while ((isr & XCAN_IXR_TXOK_MASK) && !WARN_ON(++retries == 100)) { - priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK); - isr = priv->read_reg(priv, XCAN_ISR_OFFSET); - } - - if (isr & XCAN_IXR_TXFEMP_MASK) { - /* nothing in FIFO anymore */ - frames_sent = frames_in_fifo; - } - } else { - /* single frame in fifo, just clear TXOK */ - priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK); - } - - while (frames_sent--) { can_get_echo_skb(ndev, priv->tx_tail % priv->tx_max); priv->tx_tail++; stats->tx_packets++; + isr = priv->read_reg(priv, XCAN_ISR_OFFSET); } - - netif_wake_queue(ndev); - - spin_unlock_irqrestore(&priv->tx_lock, flags); - can_led_event(ndev, CAN_LED_EVENT_TX); - xcan_update_error_state_after_rxtx(ndev); + netif_wake_queue(ndev); } /** @@ -937,7 +772,6 @@ static irqreturn_t xcan_interrupt(int irq, void *dev_id) struct net_device *ndev = (struct net_device *)dev_id; struct xcan_priv *priv = netdev_priv(ndev); u32 isr, ier; - u32 isr_errors; /* Get the interrupt status from Xilinx CAN */ isr = priv->read_reg(priv, XCAN_ISR_OFFSET); @@ -956,17 +790,18 @@ static irqreturn_t xcan_interrupt(int irq, void *dev_id) xcan_tx_interrupt(ndev, isr); /* Check for the type of error interrupt and Processing it */ - isr_errors = isr & (XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK | - XCAN_IXR_BSOFF_MASK | XCAN_IXR_ARBLST_MASK); - if (isr_errors) { - priv->write_reg(priv, XCAN_ICR_OFFSET, isr_errors); + if (isr & (XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK | + XCAN_IXR_BSOFF_MASK | XCAN_IXR_ARBLST_MASK)) { + priv->write_reg(priv, XCAN_ICR_OFFSET, (XCAN_IXR_ERROR_MASK | + XCAN_IXR_RXOFLW_MASK | XCAN_IXR_BSOFF_MASK | + XCAN_IXR_ARBLST_MASK)); xcan_err_interrupt(ndev, isr); } /* Check for the type of receive interrupt and Processing it */ - if (isr & XCAN_IXR_RXNEMP_MASK) { + if (isr & (XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK)) { ier = priv->read_reg(priv, XCAN_IER_OFFSET); - ier &= ~XCAN_IXR_RXNEMP_MASK; + ier &= ~(XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK); priv->write_reg(priv, XCAN_IER_OFFSET, ier); napi_schedule(&priv->napi); } @@ -1195,18 +1030,6 @@ static int __maybe_unused xcan_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(xcan_dev_pm_ops, xcan_suspend, xcan_resume); -static const struct xcan_devtype_data xcan_zynq_data = { - .caps = XCAN_CAP_WATERMARK, -}; - -/* Match table for OF platform binding */ -static const struct of_device_id xcan_of_match[] = { - { .compatible = "xlnx,zynq-can-1.0", .data = &xcan_zynq_data }, - { .compatible = "xlnx,axi-can-1.00.a", }, - { /* end of list */ }, -}; -MODULE_DEVICE_TABLE(of, xcan_of_match); - /** * xcan_probe - Platform registration call * @pdev: Handle to the platform device structure @@ -1221,10 +1044,8 @@ static int xcan_probe(struct platform_device *pdev) struct resource *res; /* IO mem resources */ struct net_device *ndev; struct xcan_priv *priv; - const struct of_device_id *of_id; - int caps = 0; void __iomem *addr; - int ret, rx_max, tx_max, tx_fifo_depth; + int ret, rx_max, tx_max; /* Get the virtual base address for the device */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1234,8 +1055,7 @@ static int xcan_probe(struct platform_device *pdev) goto err; } - ret = of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", - &tx_fifo_depth); + ret = of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", &tx_max); if (ret < 0) goto err; @@ -1243,30 +1063,6 @@ static int xcan_probe(struct platform_device *pdev) if (ret < 0) goto err; - of_id = of_match_device(xcan_of_match, &pdev->dev); - if (of_id) { - const struct xcan_devtype_data *devtype_data = of_id->data; - - if (devtype_data) - caps = devtype_data->caps; - } - - /* There is no way to directly figure out how many frames have been - * sent when the TXOK interrupt is processed. If watermark programming - * is supported, we can have 2 frames in the FIFO and use TXFEMP - * to determine if 1 or 2 frames have been sent. - * Theoretically we should be able to use TXFWMEMP to determine up - * to 3 frames, but it seems that after putting a second frame in the - * FIFO, with watermark at 2 frames, it can happen that TXFWMEMP (less - * than 2 frames in FIFO) is set anyway with no TXOK (a frame was - * sent), which is not a sensible state - possibly TXFWMEMP is not - * completely synchronized with the rest of the bits? - */ - if (caps & XCAN_CAP_WATERMARK) - tx_max = min(tx_fifo_depth, 2); - else - tx_max = 1; - /* Create a CAN device instance */ ndev = alloc_candev(sizeof(struct xcan_priv), tx_max); if (!ndev) @@ -1281,7 +1077,6 @@ static int xcan_probe(struct platform_device *pdev) CAN_CTRLMODE_BERR_REPORTING; priv->reg_base = addr; priv->tx_max = tx_max; - spin_lock_init(&priv->tx_lock); /* Get IRQ for the device */ ndev->irq = platform_get_irq(pdev, 0); @@ -1349,9 +1144,9 @@ static int xcan_probe(struct platform_device *pdev) devm_can_led_init(ndev); clk_disable_unprepare(priv->bus_clk); clk_disable_unprepare(priv->can_clk); - netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth: actual %d, using %d\n", + netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth:%d\n", priv->reg_base, ndev->irq, priv->can.clock.freq, - tx_fifo_depth, priv->tx_max); + priv->tx_max); return 0; @@ -1387,6 +1182,14 @@ static int xcan_remove(struct platform_device *pdev) return 0; } +/* Match table for OF platform binding */ +static const struct of_device_id xcan_of_match[] = { + { .compatible = "xlnx,zynq-can-1.0", }, + { .compatible = "xlnx,axi-can-1.00.a", }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, xcan_of_match); + static struct platform_driver xcan_driver = { .probe = xcan_probe, .remove = xcan_remove, diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 0864f05633a2..6f946fedbb77 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -1137,7 +1137,6 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phydev) { struct bcm_sf2_priv *priv = ds_to_priv(ds); - struct ethtool_eee *p = &priv->port_sts[port].eee; u32 id_mode_dis = 0, port_mode; const char *str = NULL; u32 reg; @@ -1212,9 +1211,6 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port, reg |= DUPLX_MODE; core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port)); - - if (!phydev->is_pseudo_fixed_link) - p->eee_enabled = bcm_sf2_eee_init(ds, port, phydev); } static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h index c7994e372284..6bba1c98d764 100644 --- a/drivers/net/dsa/bcm_sf2.h +++ b/drivers/net/dsa/bcm_sf2.h @@ -187,8 +187,8 @@ static inline void name##_writeq(struct bcm_sf2_priv *priv, u64 val, \ static inline void intrl2_##which##_mask_clear(struct bcm_sf2_priv *priv, \ u32 mask) \ { \ - priv->irq##which##_mask &= ~(mask); \ intrl2_##which##_writel(priv, mask, INTRL2_CPU_MASK_CLEAR); \ + priv->irq##which##_mask &= ~(mask); \ } \ static inline void intrl2_##which##_mask_set(struct bcm_sf2_priv *priv, \ u32 mask) \ diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c index 7677c745fb30..4547a1b8b958 100644 --- a/drivers/net/ethernet/3com/3c509.c +++ b/drivers/net/ethernet/3com/3c509.c @@ -562,7 +562,7 @@ static void el3_common_remove (struct net_device *dev) } #ifdef CONFIG_EISA -static int el3_eisa_probe(struct device *device) +static int __init el3_eisa_probe (struct device *device) { short i; int ioaddr, irq, if_port; diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 1c5f3b273e6a..2839af00f20c 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -907,7 +907,7 @@ static struct eisa_device_id vortex_eisa_ids[] = { }; MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids); -static int vortex_eisa_probe(struct device *device) +static int __init vortex_eisa_probe(struct device *device) { void __iomem *ioaddr; struct eisa_device *edev; diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig index 5c3ef9fc8207..5b7658bcf020 100644 --- a/drivers/net/ethernet/3com/Kconfig +++ b/drivers/net/ethernet/3com/Kconfig @@ -32,7 +32,7 @@ config EL3 config 3C515 tristate "3c515 ISA \"Fast EtherLink\"" - depends on ISA && ISA_DMA_API && !PPC32 + depends on ISA && ISA_DMA_API ---help--- If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet network card, say Y here. diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c index a0012c3cb4f6..8f8418d2ac4a 100644 --- a/drivers/net/ethernet/3com/typhoon.c +++ b/drivers/net/ethernet/3com/typhoon.c @@ -2366,9 +2366,9 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) * 4) Get the hardware address. * 5) Put the card to sleep. */ - err = typhoon_reset(ioaddr, WaitSleep); - if (err < 0) { + if (typhoon_reset(ioaddr, WaitSleep) < 0) { err_msg = "could not reset 3XP"; + err = -EIO; goto error_out_dma; } @@ -2382,25 +2382,24 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) typhoon_init_interface(tp); typhoon_init_rings(tp); - err = typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST); - if (err < 0) { + if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) { err_msg = "cannot boot 3XP sleep image"; + err = -EIO; goto error_out_reset; } INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_MAC_ADDRESS); - err = typhoon_issue_command(tp, 1, &xp_cmd, 1, xp_resp); - if (err < 0) { + if(typhoon_issue_command(tp, 1, &xp_cmd, 1, xp_resp) < 0) { err_msg = "cannot read MAC address"; + err = -EIO; goto error_out_reset; } *(__be16 *)&dev->dev_addr[0] = htons(le16_to_cpu(xp_resp[0].parm1)); *(__be32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp[0].parm2)); - if (!is_valid_ether_addr(dev->dev_addr)) { + if(!is_valid_ether_addr(dev->dev_addr)) { err_msg = "Could not obtain valid ethernet address, aborting"; - err = -EIO; goto error_out_reset; } @@ -2408,8 +2407,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) * later when we print out the version reported. */ INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_VERSIONS); - err = typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp); - if (err < 0) { + if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) { err_msg = "Could not get Sleep Image version"; goto error_out_reset; } @@ -2426,9 +2424,9 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if(xp_resp[0].numDesc != 0) tp->capabilities |= TYPHOON_WAKEUP_NEEDS_RESET; - err = typhoon_sleep(tp, PCI_D3hot, 0); - if (err < 0) { + if(typhoon_sleep(tp, PCI_D3hot, 0) < 0) { err_msg = "cannot put adapter to sleep"; + err = -EIO; goto error_out_reset; } @@ -2451,8 +2449,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->features = dev->hw_features | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_RXCSUM; - err = register_netdev(dev); - if (err < 0) { + if(register_netdev(dev) < 0) { err_msg = "unable to register netdev"; goto error_out_reset; } diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c index f089fa954f42..ac7288240d55 100644 --- a/drivers/net/ethernet/adaptec/starfire.c +++ b/drivers/net/ethernet/adaptec/starfire.c @@ -1153,12 +1153,6 @@ static void init_ring(struct net_device *dev) if (skb == NULL) break; np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(np->pci_dev, - np->rx_info[i].mapping)) { - dev_kfree_skb(skb); - np->rx_info[i].skb = NULL; - break; - } /* Grrr, we cannot offset to correctly align the IP header. */ np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid); } @@ -1189,9 +1183,8 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); unsigned int entry; - unsigned int prev_tx; u32 status; - int i, j; + int i; /* * be cautious here, wrapping the queue has weird semantics @@ -1209,7 +1202,6 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) } #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */ - prev_tx = np->cur_tx; entry = np->cur_tx % TX_RING_SIZE; for (i = 0; i < skb_num_frags(skb); i++) { int wrap_ring = 0; @@ -1243,11 +1235,6 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) skb_frag_size(this_frag), PCI_DMA_TODEVICE); } - if (pci_dma_mapping_error(np->pci_dev, - np->tx_info[entry].mapping)) { - dev->stats.tx_dropped++; - goto err_out; - } np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping); np->tx_ring[entry].status = cpu_to_le32(status); @@ -1282,31 +1269,9 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); return NETDEV_TX_OK; - -err_out: - entry = prev_tx % TX_RING_SIZE; - np->tx_info[entry].skb = NULL; - if (i > 0) { - pci_unmap_single(np->pci_dev, - np->tx_info[entry].mapping, - skb_first_frag_len(skb), - PCI_DMA_TODEVICE); - np->tx_info[entry].mapping = 0; - entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE; - for (j = 1; j < i; j++) { - pci_unmap_single(np->pci_dev, - np->tx_info[entry].mapping, - skb_frag_size( - &skb_shinfo(skb)->frags[j-1]), - PCI_DMA_TODEVICE); - entry++; - } - } - dev_kfree_skb_any(skb); - np->cur_tx = prev_tx; - return NETDEV_TX_OK; } + /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ static irqreturn_t intr_handler(int irq, void *dev_instance) @@ -1605,12 +1570,6 @@ static void refill_rx_ring(struct net_device *dev) break; /* Better luck next round. */ np->rx_info[entry].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(np->pci_dev, - np->rx_info[entry].mapping)) { - dev_kfree_skb(skb); - np->rx_info[entry].skb = NULL; - break; - } np->rx_ring[entry].rxaddr = cpu_to_dma(np->rx_info[entry].mapping | RxDescValid); } diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig index ec59425fdbff..0038709fd317 100644 --- a/drivers/net/ethernet/amd/Kconfig +++ b/drivers/net/ethernet/amd/Kconfig @@ -44,7 +44,7 @@ config AMD8111_ETH config LANCE tristate "AMD LANCE and PCnet (AT1500 and NE2100) support" - depends on ISA && ISA_DMA_API && !ARM && !PPC32 + depends on ISA && ISA_DMA_API && !ARM ---help--- If you have a network (Ethernet) card of this type, say Y here. Some LinkSys cards are of this type. @@ -138,7 +138,7 @@ config PCMCIA_NMCLAN config NI65 tristate "NI6510 support" - depends on ISA && ISA_DMA_API && !ARM && !PPC32 + depends on ISA && ISA_DMA_API && !ARM ---help--- If you have a network (Ethernet) card of this type, say Y here. diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index 66ba1e0ff37e..b6fa89102526 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -913,8 +913,8 @@ #define RX_PACKET_ATTRIBUTES_CSUM_DONE_WIDTH 1 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX 1 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1 -#define RX_PACKET_ATTRIBUTES_LAST_INDEX 2 -#define RX_PACKET_ATTRIBUTES_LAST_WIDTH 1 +#define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX 2 +#define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH 1 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX 3 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH 1 #define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX 4 @@ -923,8 +923,6 @@ #define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH 1 #define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX 6 #define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH 1 -#define RX_PACKET_ATTRIBUTES_FIRST_INDEX 7 -#define RX_PACKET_ATTRIBUTES_FIRST_WIDTH 1 #define RX_NORMAL_DESC0_OVT_INDEX 0 #define RX_NORMAL_DESC0_OVT_WIDTH 16 diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 75e6e7e6baed..f6a7161e3b85 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1658,15 +1658,10 @@ static int xgbe_dev_read(struct xgbe_channel *channel) /* Get the header length */ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) { - XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, - FIRST, 1); rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2, RX_NORMAL_DESC2, HL); if (rdata->rx.hdr_len) pdata->ext_stats.rx_split_header_packets++; - } else { - XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, - FIRST, 0); } /* Get the RSS hash */ @@ -1689,16 +1684,19 @@ static int xgbe_dev_read(struct xgbe_channel *channel) } } - /* Not all the data has been transferred for this packet */ - if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) + /* Get the packet length */ + rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); + + if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) { + /* Not all the data has been transferred for this packet */ + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + INCOMPLETE, 1); return 0; + } /* This is the last of the data for this packet */ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, - LAST, 1); - - /* Get the packet length */ - rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); + INCOMPLETE, 0); /* Set checksum done indicator as appropriate */ if (netdev->features & NETIF_F_RXCSUM) @@ -2732,10 +2730,8 @@ static int xgbe_init(struct xgbe_prv_data *pdata) /* Flush Tx queues */ ret = xgbe_flush_tx_queues(pdata); - if (ret) { - netdev_err(pdata->netdev, "error flushing TX queues\n"); + if (ret) return ret; - } /* * Initialize DMA related features diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 64034ff081a0..53ce1222b11d 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -877,9 +877,7 @@ static int xgbe_start(struct xgbe_prv_data *pdata) DBGPR("-->xgbe_start\n"); - ret = hw_if->init(pdata); - if (ret) - return ret; + hw_if->init(pdata); ret = phy_if->phy_start(pdata); if (ret) @@ -1762,12 +1760,13 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, { struct sk_buff *skb; u8 *packet; + unsigned int copy_len; skb = napi_alloc_skb(napi, rdata->rx.hdr.dma_len); if (!skb) return NULL; - /* Pull in the header buffer which may contain just the header + /* Start with the header buffer which may contain just the header * or the header plus data */ dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.hdr.dma_base, @@ -1776,49 +1775,30 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, packet = page_address(rdata->rx.hdr.pa.pages) + rdata->rx.hdr.pa.pages_offset; - skb_copy_to_linear_data(skb, packet, len); - skb_put(skb, len); + copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : len; + copy_len = min(rdata->rx.hdr.dma_len, copy_len); + skb_copy_to_linear_data(skb, packet, copy_len); + skb_put(skb, copy_len); + + len -= copy_len; + if (len) { + /* Add the remaining data as a frag */ + dma_sync_single_range_for_cpu(pdata->dev, + rdata->rx.buf.dma_base, + rdata->rx.buf.dma_off, + rdata->rx.buf.dma_len, + DMA_FROM_DEVICE); + + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, + rdata->rx.buf.pa.pages, + rdata->rx.buf.pa.pages_offset, + len, rdata->rx.buf.dma_len); + rdata->rx.buf.pa.pages = NULL; + } return skb; } -static unsigned int xgbe_rx_buf1_len(struct xgbe_ring_data *rdata, - struct xgbe_packet_data *packet) -{ - /* Always zero if not the first descriptor */ - if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, FIRST)) - return 0; - - /* First descriptor with split header, return header length */ - if (rdata->rx.hdr_len) - return rdata->rx.hdr_len; - - /* First descriptor but not the last descriptor and no split header, - * so the full buffer was used - */ - if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST)) - return rdata->rx.hdr.dma_len; - - /* First descriptor and last descriptor and no split header, so - * calculate how much of the buffer was used - */ - return min_t(unsigned int, rdata->rx.hdr.dma_len, rdata->rx.len); -} - -static unsigned int xgbe_rx_buf2_len(struct xgbe_ring_data *rdata, - struct xgbe_packet_data *packet, - unsigned int len) -{ - /* Always the full buffer if not the last descriptor */ - if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST)) - return rdata->rx.buf.dma_len; - - /* Last descriptor so calculate how much of the buffer was used - * for the last bit of data - */ - return rdata->rx.len - len; -} - static int xgbe_tx_poll(struct xgbe_channel *channel) { struct xgbe_prv_data *pdata = channel->pdata; @@ -1901,8 +1881,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) struct napi_struct *napi; struct sk_buff *skb; struct skb_shared_hwtstamps *hwtstamps; - unsigned int last, error, context_next, context; - unsigned int len, buf1_len, buf2_len, max_len; + unsigned int incomplete, error, context_next, context; + unsigned int len, rdesc_len, max_len; unsigned int received = 0; int packet_count = 0; @@ -1912,7 +1892,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) if (!ring) return 0; - last = 0; + incomplete = 0; context_next = 0; napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; @@ -1946,8 +1926,9 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) received++; ring->cur++; - last = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, - LAST); + incomplete = XGMAC_GET_BITS(packet->attributes, + RX_PACKET_ATTRIBUTES, + INCOMPLETE); context_next = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, CONTEXT_NEXT); @@ -1956,7 +1937,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) CONTEXT); /* Earlier error, just drain the remaining data */ - if ((!last || context_next) && error) + if ((incomplete || context_next) && error) goto read_again; if (error || packet->errors) { @@ -1968,22 +1949,16 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) } if (!context) { - /* Get the data length in the descriptor buffers */ - buf1_len = xgbe_rx_buf1_len(rdata, packet); - len += buf1_len; - buf2_len = xgbe_rx_buf2_len(rdata, packet, len); - len += buf2_len; + /* Length is cumulative, get this descriptor's length */ + rdesc_len = rdata->rx.len - len; + len += rdesc_len; - if (!skb) { + if (rdesc_len && !skb) { skb = xgbe_create_skb(pdata, napi, rdata, - buf1_len); - if (!skb) { + rdesc_len); + if (!skb) error = 1; - goto skip_data; - } - } - - if (buf2_len) { + } else if (rdesc_len) { dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.buf.dma_base, rdata->rx.buf.dma_off, @@ -1993,14 +1968,13 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rdata->rx.buf.pa.pages, rdata->rx.buf.pa.pages_offset, - buf2_len, + rdesc_len, rdata->rx.buf.dma_len); rdata->rx.buf.pa.pages = NULL; } } -skip_data: - if (!last || context_next) + if (incomplete || context_next) goto read_again; if (!skb) @@ -2059,7 +2033,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) } /* Check if we need to save state before leaving */ - if (received && (!last || context_next)) { + if (received && (incomplete || context_next)) { rdata = XGBE_GET_DESC_DATA(ring, ring->cur); rdata->state_saved = 1; rdata->state.skb = skb; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index 2ef4b4e884ae..618d952c2984 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -829,7 +829,7 @@ static int xgbe_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int xgbe_suspend(struct device *dev) { struct net_device *netdev = dev_get_drvdata(dev); @@ -868,7 +868,7 @@ static int xgbe_resume(struct device *dev) return ret; } -#endif /* CONFIG_PM_SLEEP */ +#endif /* CONFIG_PM */ #ifdef CONFIG_ACPI static const struct acpi_device_id xgbe_acpi_match[] = { diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 7a0ab4c44ee4..446058081866 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -872,14 +872,14 @@ static void xgbe_phy_adjust_link(struct xgbe_prv_data *pdata) if (pdata->tx_pause != pdata->phy.tx_pause) { new_state = 1; - pdata->tx_pause = pdata->phy.tx_pause; pdata->hw_if.config_tx_flow_control(pdata); + pdata->tx_pause = pdata->phy.tx_pause; } if (pdata->rx_pause != pdata->phy.rx_pause) { new_state = 1; - pdata->rx_pause = pdata->phy.rx_pause; pdata->hw_if.config_rx_flow_control(pdata); + pdata->rx_pause = pdata->phy.rx_pause; } /* Speed support */ diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c index e8d31640058d..c31e691d11fc 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c @@ -604,7 +604,6 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata, xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb); cb |= CFG_CLE_BYPASS_EN0; CFG_CLE_IP_PROTOCOL0_SET(&cb, 3); - CFG_CLE_IP_HDR_LEN_SET(&cb, 0); xgene_enet_wr_csr(pdata, CLE_BYPASS_REG0_0_ADDR, cb); xgene_enet_rd_csr(pdata, CLE_BYPASS_REG1_0_ADDR, &cb); diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h index 480312105964..c153a1dc5ff7 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h @@ -147,7 +147,6 @@ enum xgene_enet_rm { #define CFG_RXCLK_MUXSEL0_SET(dst, val) xgene_set_bits(dst, val, 26, 3) #define CFG_CLE_IP_PROTOCOL0_SET(dst, val) xgene_set_bits(dst, val, 16, 2) -#define CFG_CLE_IP_HDR_LEN_SET(dst, val) xgene_set_bits(dst, val, 8, 5) #define CFG_CLE_DSTQID0_SET(dst, val) xgene_set_bits(dst, val, 0, 12) #define CFG_CLE_FPSEL0_SET(dst, val) xgene_set_bits(dst, val, 16, 4) #define CFG_MACMODE_SET(dst, val) xgene_set_bits(dst, val, 18, 2) diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index 9cc5daed13ed..abe1eabc0171 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -250,48 +250,39 @@ static int arc_emac_rx(struct net_device *ndev, int budget) continue; } - /* Prepare the BD for next cycle. netif_receive_skb() - * only if new skb was allocated and mapped to avoid holes - * in the RX fifo. - */ - skb = netdev_alloc_skb_ip_align(ndev, EMAC_BUFFER_SIZE); - if (unlikely(!skb)) { - if (net_ratelimit()) - netdev_err(ndev, "cannot allocate skb\n"); - /* Return ownership to EMAC */ - rxbd->info = cpu_to_le32(FOR_EMAC | EMAC_BUFFER_SIZE); + pktlen = info & LEN_MASK; + stats->rx_packets++; + stats->rx_bytes += pktlen; + skb = rx_buff->skb; + skb_put(skb, pktlen); + skb->dev = ndev; + skb->protocol = eth_type_trans(skb, ndev); + + dma_unmap_single(&ndev->dev, dma_unmap_addr(rx_buff, addr), + dma_unmap_len(rx_buff, len), DMA_FROM_DEVICE); + + /* Prepare the BD for next cycle */ + rx_buff->skb = netdev_alloc_skb_ip_align(ndev, + EMAC_BUFFER_SIZE); + if (unlikely(!rx_buff->skb)) { stats->rx_errors++; + /* Because receive_skb is below, increment rx_dropped */ stats->rx_dropped++; continue; } - addr = dma_map_single(&ndev->dev, (void *)skb->data, + /* receive_skb only if new skb was allocated to avoid holes */ + netif_receive_skb(skb); + + addr = dma_map_single(&ndev->dev, (void *)rx_buff->skb->data, EMAC_BUFFER_SIZE, DMA_FROM_DEVICE); if (dma_mapping_error(&ndev->dev, addr)) { if (net_ratelimit()) - netdev_err(ndev, "cannot map dma buffer\n"); - dev_kfree_skb(skb); - /* Return ownership to EMAC */ - rxbd->info = cpu_to_le32(FOR_EMAC | EMAC_BUFFER_SIZE); + netdev_err(ndev, "cannot dma map\n"); + dev_kfree_skb(rx_buff->skb); stats->rx_errors++; - stats->rx_dropped++; continue; } - - /* unmap previosly mapped skb */ - dma_unmap_single(&ndev->dev, dma_unmap_addr(rx_buff, addr), - dma_unmap_len(rx_buff, len), DMA_FROM_DEVICE); - - pktlen = info & LEN_MASK; - stats->rx_packets++; - stats->rx_bytes += pktlen; - skb_put(rx_buff->skb, pktlen); - rx_buff->skb->dev = ndev; - rx_buff->skb->protocol = eth_type_trans(rx_buff->skb, ndev); - - netif_receive_skb(rx_buff->skb); - - rx_buff->skb = skb; dma_unmap_addr_set(rx_buff, addr, addr); dma_unmap_len_set(rx_buff, len, EMAC_BUFFER_SIZE); diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c index 425dae560322..c31c7407b753 100644 --- a/drivers/net/ethernet/arc/emac_rockchip.c +++ b/drivers/net/ethernet/arc/emac_rockchip.c @@ -150,10 +150,8 @@ static int emac_rockchip_probe(struct platform_device *pdev) /* Optional regulator for PHY */ priv->regulator = devm_regulator_get_optional(dev, "phy"); if (IS_ERR(priv->regulator)) { - if (PTR_ERR(priv->regulator) == -EPROBE_DEFER) { - err = -EPROBE_DEFER; - goto out_clk_disable; - } + if (PTR_ERR(priv->regulator) == -EPROBE_DEFER) + return -EPROBE_DEFER; dev_err(dev, "no regulator found\n"); priv->regulator = NULL; } diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index df54475d163b..bd377a6b067d 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -86,14 +86,9 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp) while (!cur_buf->skb && next != rxq->read_idx) { struct alx_rfd *rfd = &rxq->rfd[cur]; - skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size + 64, gfp); + skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp); if (!skb) break; - - /* Workround for the HW RX DMA overflow issue */ - if (((unsigned long)skb->data & 0xfff) == 0xfc0) - skb_reserve(skb, 64); - dma = dma_map_single(&alx->hw.pdev->dev, skb->data, alx->rxbuf_size, DMA_FROM_DEVICE); diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index c08d34f618b9..8b5988e210d5 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -1683,7 +1683,6 @@ static struct sk_buff *atl1c_alloc_skb(struct atl1c_adapter *adapter) skb = build_skb(page_address(page) + adapter->rx_page_offset, adapter->rx_frag_size); if (likely(skb)) { - skb_reserve(skb, NET_SKB_PAD); adapter->rx_page_offset += adapter->rx_frag_size; if (adapter->rx_page_offset >= PAGE_SIZE) adapter->rx_page = NULL; diff --git a/drivers/net/ethernet/aurora/nb8800.c b/drivers/net/ethernet/aurora/nb8800.c index 0a54e7dac0ab..ecc4a334c507 100644 --- a/drivers/net/ethernet/aurora/nb8800.c +++ b/drivers/net/ethernet/aurora/nb8800.c @@ -608,7 +608,7 @@ static void nb8800_mac_config(struct net_device *dev) mac_mode |= HALF_DUPLEX; if (gigabit) { - if (phy_interface_is_rgmii(dev->phydev)) + if (priv->phy_mode == PHY_INTERFACE_MODE_RGMII) mac_mode |= RGMII_MODE; mac_mode |= GMAC_MODE; @@ -1295,12 +1295,13 @@ static int nb8800_tangox_init(struct net_device *dev) break; case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: pad_mode = PAD_MODE_RGMII; break; + case PHY_INTERFACE_MODE_RGMII_TXID: + pad_mode = PAD_MODE_RGMII | PAD_MODE_GTX_CLK_DELAY; + break; + default: dev_err(dev->dev.parent, "unsupported phy mode %s\n", phy_modes(priv->phy_mode)); diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index ec5834087e4b..8b1929e9f698 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -1063,8 +1063,7 @@ static int bcm_enet_open(struct net_device *dev) val = enet_readl(priv, ENET_CTL_REG); val |= ENET_CTL_ENABLE_MASK; enet_writel(priv, val, ENET_CTL_REG); - if (priv->dma_has_sram) - enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); + enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); enet_dmac_writel(priv, priv->dma_chan_en_mask, ENETDMAC_CHANCFG, priv->rx_chan); @@ -1788,9 +1787,7 @@ static int bcm_enet_probe(struct platform_device *pdev) ret = PTR_ERR(priv->mac_clk); goto out; } - ret = clk_prepare_enable(priv->mac_clk); - if (ret) - goto out_put_clk_mac; + clk_prepare_enable(priv->mac_clk); /* initialize default and fetch platform data */ priv->rx_ring_size = BCMENET_DEF_RX_DESC; @@ -1822,11 +1819,9 @@ static int bcm_enet_probe(struct platform_device *pdev) if (IS_ERR(priv->phy_clk)) { ret = PTR_ERR(priv->phy_clk); priv->phy_clk = NULL; - goto out_disable_clk_mac; + goto out_put_clk_mac; } - ret = clk_prepare_enable(priv->phy_clk); - if (ret) - goto out_put_clk_phy; + clk_prepare_enable(priv->phy_clk); } /* do minimal hardware init to be able to probe mii bus */ @@ -1926,16 +1921,13 @@ static int bcm_enet_probe(struct platform_device *pdev) out_uninit_hw: /* turn off mdc clock */ enet_writel(priv, 0, ENET_MIISC_REG); - if (priv->phy_clk) + if (priv->phy_clk) { clk_disable_unprepare(priv->phy_clk); - -out_put_clk_phy: - if (priv->phy_clk) clk_put(priv->phy_clk); + } -out_disable_clk_mac: - clk_disable_unprepare(priv->mac_clk); out_put_clk_mac: + clk_disable_unprepare(priv->mac_clk); clk_put(priv->mac_clk); out: free_netdev(dev); @@ -2780,9 +2772,7 @@ static int bcm_enetsw_probe(struct platform_device *pdev) ret = PTR_ERR(priv->mac_clk); goto out_unmap; } - ret = clk_prepare_enable(priv->mac_clk); - if (ret) - goto out_put_clk; + clk_enable(priv->mac_clk); priv->rx_chan = 0; priv->tx_chan = 1; @@ -2803,7 +2793,7 @@ static int bcm_enetsw_probe(struct platform_device *pdev) ret = register_netdev(dev); if (ret) - goto out_disable_clk; + goto out_put_clk; netif_carrier_off(dev); platform_set_drvdata(pdev, dev); @@ -2812,9 +2802,6 @@ static int bcm_enetsw_probe(struct platform_device *pdev) return 0; -out_disable_clk: - clk_disable_unprepare(priv->mac_clk); - out_put_clk: clk_put(priv->mac_clk); @@ -2846,9 +2833,6 @@ static int bcm_enetsw_remove(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, resource_size(res)); - clk_disable_unprepare(priv->mac_clk); - clk_put(priv->mac_clk); - free_netdev(dev); return 0; } diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index af9ec57bbebf..858106352ce9 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -729,37 +729,47 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv, struct bcm_sysport_tx_ring *ring) { struct net_device *ndev = priv->netdev; + unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs; unsigned int pkts_compl = 0, bytes_compl = 0; - unsigned int txbds_processed = 0; struct bcm_sysport_cb *cb; - unsigned int txbds_ready; - unsigned int c_index; + struct netdev_queue *txq; u32 hw_ind; + txq = netdev_get_tx_queue(ndev, ring->index); + /* Compute how many descriptors have been processed since last call */ hw_ind = tdma_readl(priv, TDMA_DESC_RING_PROD_CONS_INDEX(ring->index)); c_index = (hw_ind >> RING_CONS_INDEX_SHIFT) & RING_CONS_INDEX_MASK; - txbds_ready = (c_index - ring->c_index) & RING_CONS_INDEX_MASK; + ring->p_index = (hw_ind & RING_PROD_INDEX_MASK); + + last_c_index = ring->c_index; + num_tx_cbs = ring->size; + + c_index &= (num_tx_cbs - 1); + + if (c_index >= last_c_index) + last_tx_cn = c_index - last_c_index; + else + last_tx_cn = num_tx_cbs - last_c_index + c_index; netif_dbg(priv, tx_done, ndev, - "ring=%d old_c_index=%u c_index=%u txbds_ready=%u\n", - ring->index, ring->c_index, c_index, txbds_ready); + "ring=%d c_index=%d last_tx_cn=%d last_c_index=%d\n", + ring->index, c_index, last_tx_cn, last_c_index); - while (txbds_processed < txbds_ready) { - cb = &ring->cbs[ring->clean_index]; + while (last_tx_cn-- > 0) { + cb = ring->cbs + last_c_index; bcm_sysport_tx_reclaim_one(priv, cb, &bytes_compl, &pkts_compl); ring->desc_count++; - txbds_processed++; - - if (likely(ring->clean_index < ring->size - 1)) - ring->clean_index++; - else - ring->clean_index = 0; + last_c_index++; + last_c_index &= (num_tx_cbs - 1); } ring->c_index = c_index; + if (netif_tx_queue_stopped(txq) && pkts_compl) + netif_tx_wake_queue(txq); + netif_dbg(priv, tx_done, ndev, "ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n", ring->index, ring->c_index, pkts_compl, bytes_compl); @@ -771,33 +781,16 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv, static unsigned int bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv, struct bcm_sysport_tx_ring *ring) { - struct netdev_queue *txq; unsigned int released; unsigned long flags; - txq = netdev_get_tx_queue(priv->netdev, ring->index); - spin_lock_irqsave(&ring->lock, flags); released = __bcm_sysport_tx_reclaim(priv, ring); - if (released) - netif_tx_wake_queue(txq); - spin_unlock_irqrestore(&ring->lock, flags); return released; } -/* Locked version of the per-ring TX reclaim, but does not wake the queue */ -static void bcm_sysport_tx_clean(struct bcm_sysport_priv *priv, - struct bcm_sysport_tx_ring *ring) -{ - unsigned long flags; - - spin_lock_irqsave(&ring->lock, flags); - __bcm_sysport_tx_reclaim(priv, ring); - spin_unlock_irqrestore(&ring->lock, flags); -} - static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget) { struct bcm_sysport_tx_ring *ring = @@ -1041,6 +1034,15 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb, goto out; } + /* Insert TSB and checksum infos */ + if (priv->tsb_en) { + skb = bcm_sysport_insert_tsb(skb, dev); + if (!skb) { + ret = NETDEV_TX_OK; + goto out; + } + } + /* The Ethernet switch we are interfaced with needs packets to be at * least 64 bytes (including FCS) otherwise they will be discarded when * they enter the switch port logic. When Broadcom tags are enabled, we @@ -1048,21 +1050,13 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb, * (including FCS and tag) because the length verification is done after * the Broadcom tag is stripped off the ingress packet. */ - if (skb_put_padto(skb, ETH_ZLEN + ENET_BRCM_TAG_LEN)) { + if (skb_padto(skb, ETH_ZLEN + ENET_BRCM_TAG_LEN)) { ret = NETDEV_TX_OK; goto out; } - /* Insert TSB and checksum infos */ - if (priv->tsb_en) { - skb = bcm_sysport_insert_tsb(skb, dev); - if (!skb) { - ret = NETDEV_TX_OK; - goto out; - } - } - - skb_len = skb->len; + skb_len = skb->len < ETH_ZLEN + ENET_BRCM_TAG_LEN ? + ETH_ZLEN + ENET_BRCM_TAG_LEN : skb->len; mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE); if (dma_mapping_error(kdev, mapping)) { @@ -1225,7 +1219,6 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv, netif_napi_add(priv->netdev, &ring->napi, bcm_sysport_tx_poll, 64); ring->index = index; ring->size = size; - ring->clean_index = 0; ring->alloc_size = ring->size; ring->desc_cpu = p; ring->desc_count = ring->size; @@ -1282,7 +1275,7 @@ static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv, napi_disable(&ring->napi); netif_napi_del(&ring->napi); - bcm_sysport_tx_clean(priv, ring); + bcm_sysport_tx_reclaim(priv, ring); kfree(ring->cbs); ring->cbs = NULL; diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h index 8ace6ecb5f79..f28bf545d7f4 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.h +++ b/drivers/net/ethernet/broadcom/bcmsysport.h @@ -638,7 +638,7 @@ struct bcm_sysport_tx_ring { unsigned int desc_count; /* Number of descriptors */ unsigned int curr_desc; /* Current descriptor */ unsigned int c_index; /* Last consumer index */ - unsigned int clean_index; /* Current clean index */ + unsigned int p_index; /* Current producer index */ struct bcm_sysport_cb *cbs; /* Transmit control blocks */ struct dma_desc *desc_cpu; /* CPU view of the descriptor */ struct bcm_sysport_priv *priv; /* private context backpointer */ diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index ec3766264408..28f7610b03fe 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -219,7 +219,7 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac, dma_unmap_single(dma_dev, slot->dma_addr, skb_headlen(skb), DMA_TO_DEVICE); - while (i-- > 0) { + while (i > 0) { int index = (ring->end + i) % BGMAC_TX_RING_SLOTS; struct bgmac_slot_info *slot = &ring->slots[index]; u32 ctl1 = le32_to_cpu(ring->cpu_base[index].ctl1); @@ -255,16 +255,15 @@ static void bgmac_dma_tx_free(struct bgmac *bgmac, struct bgmac_dma_ring *ring) while (ring->start != ring->end) { int slot_idx = ring->start % BGMAC_TX_RING_SLOTS; struct bgmac_slot_info *slot = &ring->slots[slot_idx]; - u32 ctl0, ctl1; + u32 ctl1; int len; if (slot_idx == empty_slot) break; - ctl0 = le32_to_cpu(ring->cpu_base[slot_idx].ctl0); ctl1 = le32_to_cpu(ring->cpu_base[slot_idx].ctl1); len = ctl1 & BGMAC_DESC_CTL1_LEN; - if (ctl0 & BGMAC_DESC_CTL0_SOF) + if (ctl1 & BGMAC_DESC_CTL0_SOF) /* Unmap no longer used buffer */ dma_unmap_single(dma_dev, slot->dma_addr, len, DMA_TO_DEVICE); @@ -315,10 +314,6 @@ static void bgmac_dma_rx_enable(struct bgmac *bgmac, u32 ctl; ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL); - - /* preserve ONLY bits 16-17 from current hardware value */ - ctl &= BGMAC_DMA_RX_ADDREXT_MASK; - if (bgmac->core->id.rev >= 4) { ctl &= ~BGMAC_DMA_RX_BL_MASK; ctl |= BGMAC_DMA_RX_BL_128 << BGMAC_DMA_RX_BL_SHIFT; @@ -329,6 +324,7 @@ static void bgmac_dma_rx_enable(struct bgmac *bgmac, ctl &= ~BGMAC_DMA_RX_PT_MASK; ctl |= BGMAC_DMA_RX_PT_1 << BGMAC_DMA_RX_PT_SHIFT; } + ctl &= BGMAC_DMA_RX_ADDREXT_MASK; ctl |= BGMAC_DMA_RX_ENABLE; ctl |= BGMAC_DMA_RX_PARITY_DISABLE; ctl |= BGMAC_DMA_RX_OVERFLOW_CONT; @@ -470,11 +466,6 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, len -= ETH_FCS_LEN; skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE); - if (unlikely(!skb)) { - bgmac_err(bgmac, "build_skb failed\n"); - put_page(virt_to_head_page(buf)); - break; - } skb_put(skb, BGMAC_RX_FRAME_OFFSET + BGMAC_RX_BUF_OFFSET + len); skb_pull(skb, BGMAC_RX_FRAME_OFFSET + @@ -531,8 +522,7 @@ static void bgmac_dma_tx_ring_free(struct bgmac *bgmac, int i; for (i = 0; i < BGMAC_TX_RING_SLOTS; i++) { - u32 ctl1 = le32_to_cpu(dma_desc[i].ctl1); - unsigned int len = ctl1 & BGMAC_DESC_CTL1_LEN; + int len = dma_desc[i].ctl1 & BGMAC_DESC_CTL1_LEN; slot = &ring->slots[i]; dev_kfree_skb(slot->skb); @@ -1309,8 +1299,7 @@ static int bgmac_open(struct net_device *net_dev) phy_start(bgmac->phy_dev); - netif_start_queue(net_dev); - + netif_carrier_on(net_dev); return 0; } @@ -1584,11 +1573,6 @@ static int bgmac_probe(struct bcma_device *core) dev_warn(&core->dev, "Using random MAC: %pM\n", mac); } - /* This (reset &) enable is not preset in specs or reference driver but - * Broadcom does it in arch PCI code when enabling fake PCI device. - */ - bcma_core_enable(core, 0); - /* Allocation and references */ net_dev = alloc_etherdev(sizeof(*bgmac)); if (!net_dev) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 1ea068815419..b5e64b02200c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1634,7 +1634,6 @@ struct bnx2x { struct link_vars link_vars; u32 link_cnt; struct bnx2x_link_report_data last_reported_link; - bool force_link_down; struct mdio_if_info mdio; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index ebc4518d598a..c82ab87fcbe8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1277,11 +1277,6 @@ void __bnx2x_link_report(struct bnx2x *bp) { struct bnx2x_link_report_data cur_data; - if (bp->force_link_down) { - bp->link_vars.link_up = 0; - return; - } - /* reread mf_cfg */ if (IS_PF(bp) && !CHIP_IS_E1(bp)) bnx2x_read_mf_cfg(bp); @@ -1954,7 +1949,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb, } /* select a non-FCoE queue */ - return fallback(dev, skb) % (BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos); + return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp); } void bnx2x_set_num_queues(struct bnx2x *bp) @@ -2049,7 +2044,6 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp) ETH_OVREHEAD + mtu + BNX2X_FW_RX_ALIGN_END; - fp->rx_buf_size = SKB_DATA_ALIGN(fp->rx_buf_size); /* Note : rx_buf_size doesn't take into account NET_SKB_PAD */ if (fp->rx_buf_size + NET_SKB_PAD <= PAGE_SIZE) fp->rx_frag_size = fp->rx_buf_size + NET_SKB_PAD; @@ -2845,7 +2839,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->pending_max = 0; } - bp->force_link_down = false; if (bp->port.pmf) { rc = bnx2x_initial_phy_init(bp, load_mode); if (rc) @@ -3059,7 +3052,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) del_timer_sync(&bp->timer); - if (IS_PF(bp) && !BP_NOMCP(bp)) { + if (IS_PF(bp)) { /* Set ALWAYS_ALIVE bit in shmem */ bp->fw_drv_pulse_wr_seq |= DRV_PULSE_ALWAYS_ALIVE; bnx2x_drv_pulse(bp); @@ -3141,7 +3134,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) bp->cnic_loaded = false; /* Clear driver version indication in shmem */ - if (IS_PF(bp) && !BP_NOMCP(bp)) + if (IS_PF(bp)) bnx2x_update_mng_version(bp); /* Check if there are pending parity attentions. If there are - set @@ -3949,26 +3942,15 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) /* when transmitting in a vf, start bd must hold the ethertype * for fw to enforce it */ - u16 vlan_tci = 0; #ifndef BNX2X_STOP_ON_ERROR - if (IS_VF(bp)) { + if (IS_VF(bp)) #endif - /* Still need to consider inband vlan for enforced */ - if (__vlan_get_tag(skb, &vlan_tci)) { - tx_start_bd->vlan_or_ethertype = - cpu_to_le16(ntohs(eth->h_proto)); - } else { - tx_start_bd->bd_flags.as_bitfield |= - (X_ETH_INBAND_VLAN << - ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT); - tx_start_bd->vlan_or_ethertype = - cpu_to_le16(vlan_tci); - } + tx_start_bd->vlan_or_ethertype = + cpu_to_le16(ntohs(eth->h_proto)); #ifndef BNX2X_STOP_ON_ERROR - } else { + else /* used by FW for packet accounting */ tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod); - } #endif } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index c56b61dce2d1..d84efcd34fac 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -3360,18 +3360,14 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info) DP(BNX2X_MSG_ETHTOOL, "rss re-configured, UDP 4-tupple %s\n", udp_rss_requested ? "enabled" : "disabled"); - if (bp->state == BNX2X_STATE_OPEN) - return bnx2x_rss(bp, &bp->rss_conf_obj, false, - true); + return bnx2x_rss(bp, &bp->rss_conf_obj, false, true); } else if ((info->flow_type == UDP_V6_FLOW) && (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) { bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; DP(BNX2X_MSG_ETHTOOL, "rss re-configured, UDP 4-tupple %s\n", udp_rss_requested ? "enabled" : "disabled"); - if (bp->state == BNX2X_STATE_OPEN) - return bnx2x_rss(bp, &bp->rss_conf_obj, false, - true); + return bnx2x_rss(bp, &bp->rss_conf_obj, false, true); } return 0; @@ -3485,10 +3481,7 @@ static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir, bp->rss_conf_obj.ind_table[i] = indir[i] + bp->fp->cl_id; } - if (bp->state == BNX2X_STATE_OPEN) - return bnx2x_config_rss_eth(bp, false); - - return 0; + return bnx2x_config_rss_eth(bp, false); } /** diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 87534c6efd66..d946bba43726 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -594,7 +594,7 @@ static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params, * slots for the highest priority. */ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS : - NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100); + NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100); /* Mapping between the CREDIT_WEIGHT registers and actual client * numbers */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 403fa8d98aa3..2e611dc5f162 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -9570,15 +9570,6 @@ static int bnx2x_init_shmem(struct bnx2x *bp) do { bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR); - - /* If we read all 0xFFs, means we are in PCI error state and - * should bail out to avoid crashes on adapter's FW reads. - */ - if (bp->common.shmem_base == 0xFFFFFFFF) { - bp->flags |= NO_MCP_FLAG; - return -ENODEV; - } - if (bp->common.shmem_base) { val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]); if (val & SHR_MEM_VALIDITY_MB) @@ -10222,12 +10213,6 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work) bp->sp_rtnl_state = 0; smp_mb(); - /* Immediately indicate link as down */ - bp->link_vars.link_up = 0; - bp->force_link_down = true; - netif_carrier_off(bp->dev); - BNX2X_ERR("Indicating link is down due to Tx-timeout\n"); - bnx2x_nic_unload(bp, UNLOAD_NORMAL, true); bnx2x_nic_load(bp, LOAD_NORMAL); @@ -13661,7 +13646,7 @@ static int bnx2x_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) if (!netif_running(bp->dev)) { DP(BNX2X_MSG_PTP, "PTP adjfreq called while the interface is down\n"); - return -ENETDOWN; + return -EFAULT; } if (ppb < 0) { @@ -13720,12 +13705,6 @@ static int bnx2x_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) { struct bnx2x *bp = container_of(ptp, struct bnx2x, ptp_clock_info); - if (!netif_running(bp->dev)) { - DP(BNX2X_MSG_PTP, - "PTP adjtime called while the interface is down\n"); - return -ENETDOWN; - } - DP(BNX2X_MSG_PTP, "PTP adjtime called, delta = %llx\n", delta); timecounter_adjtime(&bp->timecounter, delta); @@ -13738,12 +13717,6 @@ static int bnx2x_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) struct bnx2x *bp = container_of(ptp, struct bnx2x, ptp_clock_info); u64 ns; - if (!netif_running(bp->dev)) { - DP(BNX2X_MSG_PTP, - "PTP gettime called while the interface is down\n"); - return -ENETDOWN; - } - ns = timecounter_read(&bp->timecounter); DP(BNX2X_MSG_PTP, "PTP gettime called, ns = %llu\n", ns); @@ -13759,12 +13732,6 @@ static int bnx2x_ptp_settime(struct ptp_clock_info *ptp, struct bnx2x *bp = container_of(ptp, struct bnx2x, ptp_clock_info); u64 ns; - if (!netif_running(bp->dev)) { - DP(BNX2X_MSG_PTP, - "PTP settime called while the interface is down\n"); - return -ENETDOWN; - } - ns = timespec64_to_ns(ts); DP(BNX2X_MSG_PTP, "PTP settime called, ns = %llu\n", ns); @@ -14229,10 +14196,7 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev) BNX2X_ERR("IO slot reset --> driver unload\n"); /* MCP should have been reset; Need to wait for validity */ - if (bnx2x_init_shmem(bp)) { - rtnl_unlock(); - return PCI_ERS_RESULT_DISCONNECT; - } + bnx2x_init_shmem(bp); if (IS_PF(bp) && SHMEM2_HAS(bp, drv_capabilities_flag)) { u32 v; @@ -14855,10 +14819,6 @@ static int bnx2x_get_fc_npiv(struct net_device *dev, } offset = SHMEM2_RD(bp, fc_npiv_nvram_tbl_addr[BP_PORT(bp)]); - if (!offset) { - DP(BNX2X_MSG_MCP, "No FC-NPIV in NVRAM\n"); - goto out; - } DP(BNX2X_MSG_MCP, "Offset of FC-NPIV in NVRAM: %08x\n", offset); /* Read the table contents from nvram */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 5780830f78ad..9d027348cd09 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -434,9 +434,7 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp, /* Add/Remove the filter */ rc = bnx2x_config_vlan_mac(bp, &ramrod); - if (rc == -EEXIST) - return 0; - if (rc) { + if (rc && rc != -EEXIST) { BNX2X_ERR("Failed to %s %s\n", filter->add ? "add" : "delete", (filter->type == BNX2X_VF_FILTER_VLAN_MAC) ? @@ -446,8 +444,6 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp, return rc; } - filter->applied = true; - return 0; } @@ -475,8 +471,6 @@ int bnx2x_vf_mac_vlan_config_list(struct bnx2x *bp, struct bnx2x_virtf *vf, BNX2X_ERR("Managed only %d/%d filters - rolling back\n", i, filters->count + 1); while (--i >= 0) { - if (!filters->filters[i].applied) - continue; filters->filters[i].add = !filters->filters[i].add; bnx2x_vf_mac_vlan_config(bp, vf, qid, &filters->filters[i], diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 6f6f13dc2be3..670a581ffabc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -114,7 +114,6 @@ struct bnx2x_vf_mac_vlan_filter { (BNX2X_VF_FILTER_MAC | BNX2X_VF_FILTER_VLAN) /*shortcut*/ bool add; - bool applied; u8 *mac; u16 vid; }; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index a12a4236b143..1374e5394a79 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -868,7 +868,7 @@ int bnx2x_vfpf_set_mcast(struct net_device *dev) struct bnx2x *bp = netdev_priv(dev); struct vfpf_set_q_filters_tlv *req = &bp->vf2pf_mbox->req.set_q_filters; struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp; - int rc = 0, i = 0; + int rc, i = 0; struct netdev_hw_addr *ha; if (bp->state != BNX2X_STATE_OPEN) { @@ -883,15 +883,6 @@ int bnx2x_vfpf_set_mcast(struct net_device *dev) /* Get Rx mode requested */ DP(NETIF_MSG_IFUP, "dev->flags = %x\n", dev->flags); - /* We support PFVF_MAX_MULTICAST_PER_VF mcast addresses tops */ - if (netdev_mc_count(dev) > PFVF_MAX_MULTICAST_PER_VF) { - DP(NETIF_MSG_IFUP, - "VF supports not more than %d multicast MAC addresses\n", - PFVF_MAX_MULTICAST_PER_VF); - rc = -EINVAL; - goto out; - } - netdev_for_each_mc_addr(ha, dev) { DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n", bnx2x_mc_addr(ha)); @@ -899,6 +890,16 @@ int bnx2x_vfpf_set_mcast(struct net_device *dev) i++; } + /* We support four PFVF_MAX_MULTICAST_PER_VF mcast + * addresses tops + */ + if (i >= PFVF_MAX_MULTICAST_PER_VF) { + DP(NETIF_MSG_IFUP, + "VF supports not more than %d multicast MAC addresses\n", + PFVF_MAX_MULTICAST_PER_VF); + return -EINVAL; + } + req->n_multicast = i; req->flags |= VFPF_SET_Q_FILTERS_MULTICAST_CHANGED; req->vf_qid = 0; @@ -923,7 +924,7 @@ int bnx2x_vfpf_set_mcast(struct net_device *dev) out: bnx2x_vfpf_finalize(bp, &req->first_tlv); - return rc; + return 0; } /* request pf to add a vlan for the vf */ diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 4ffacafddacb..07f5f239cb65 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2014,18 +2014,6 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr) return 0; } -static void bnxt_init_cp_rings(struct bnxt *bp) -{ - int i; - - for (i = 0; i < bp->cp_nr_rings; i++) { - struct bnxt_cp_ring_info *cpr = &bp->bnapi[i]->cp_ring; - struct bnxt_ring_struct *ring = &cpr->cp_ring_struct; - - ring->fw_ring_id = INVALID_HW_RING_ID; - } -} - static int bnxt_init_rx_rings(struct bnxt *bp) { int i, rc = 0; @@ -2485,8 +2473,7 @@ static int bnxt_alloc_ntp_fltrs(struct bnxt *bp) INIT_HLIST_HEAD(&bp->ntp_fltr_hash_tbl[i]); bp->ntp_fltr_count = 0; - bp->ntp_fltr_bmap = kcalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR), - sizeof(long), + bp->ntp_fltr_bmap = kzalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR), GFP_KERNEL); if (!bp->ntp_fltr_bmap) @@ -2925,9 +2912,6 @@ static int bnxt_hwrm_vnic_set_tpa(struct bnxt *bp, u16 vnic_id, u32 tpa_flags) struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id]; struct hwrm_vnic_tpa_cfg_input req = {0}; - if (vnic->fw_vnic_id == INVALID_HW_RING_ID) - return 0; - bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_TPA_CFG, -1, -1); if (tpa_flags) { @@ -3992,7 +3976,6 @@ static int bnxt_shutdown_nic(struct bnxt *bp, bool irq_re_init) static int bnxt_init_nic(struct bnxt *bp, bool irq_re_init) { - bnxt_init_cp_rings(bp); bnxt_init_rx_rings(bp); bnxt_init_tx_rings(bp); bnxt_init_ring_grps(bp, irq_re_init); @@ -4591,7 +4574,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) rc = bnxt_request_irq(bp); if (rc) { netdev_err(bp->dev, "bnxt_request_irq err: %x\n", rc); - goto open_err_irq; + goto open_err; } } @@ -4629,8 +4612,6 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) open_err: bnxt_disable_napi(bp); - -open_err_irq: bnxt_del_napi(bp); open_err_free_mem: diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c index 3eebb57975e3..ea044bbcd384 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c @@ -29,7 +29,7 @@ static int bnxt_vf_ndo_prep(struct bnxt *bp, int vf_id) netdev_err(bp->dev, "vf ndo called though sriov is disabled\n"); return -EINVAL; } - if (vf_id >= bp->pf.active_vfs) { + if (vf_id >= bp->pf.max_vfs) { netdev_err(bp->dev, "Invalid VF id %d\n", vf_id); return -EINVAL; } diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 74dd48f2bd89..0fb3f8de88e9 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1,7 +1,7 @@ /* * Broadcom GENET (Gigabit Ethernet) controller driver * - * Copyright (c) 2014-2017 Broadcom + * Copyright (c) 2014 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -778,9 +778,8 @@ static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = { STAT_GENET_RUNT("rx_runt_bytes", mib.rx_runt_bytes), /* Misc UniMAC counters */ STAT_GENET_MISC("rbuf_ovflow_cnt", mib.rbuf_ovflow_cnt, - UMAC_RBUF_OVFL_CNT_V1), - STAT_GENET_MISC("rbuf_err_cnt", mib.rbuf_err_cnt, - UMAC_RBUF_ERR_CNT_V1), + UMAC_RBUF_OVFL_CNT), + STAT_GENET_MISC("rbuf_err_cnt", mib.rbuf_err_cnt, UMAC_RBUF_ERR_CNT), STAT_GENET_MISC("mdf_err_cnt", mib.mdf_err_cnt, UMAC_MDF_ERR_CNT), STAT_GENET_SOFT_MIB("alloc_rx_buff_failed", mib.alloc_rx_buff_failed), STAT_GENET_SOFT_MIB("rx_dma_failed", mib.rx_dma_failed), @@ -822,45 +821,6 @@ static void bcmgenet_get_strings(struct net_device *dev, u32 stringset, } } -static u32 bcmgenet_update_stat_misc(struct bcmgenet_priv *priv, u16 offset) -{ - u16 new_offset; - u32 val; - - switch (offset) { - case UMAC_RBUF_OVFL_CNT_V1: - if (GENET_IS_V2(priv)) - new_offset = RBUF_OVFL_CNT_V2; - else - new_offset = RBUF_OVFL_CNT_V3PLUS; - - val = bcmgenet_rbuf_readl(priv, new_offset); - /* clear if overflowed */ - if (val == ~0) - bcmgenet_rbuf_writel(priv, 0, new_offset); - break; - case UMAC_RBUF_ERR_CNT_V1: - if (GENET_IS_V2(priv)) - new_offset = RBUF_ERR_CNT_V2; - else - new_offset = RBUF_ERR_CNT_V3PLUS; - - val = bcmgenet_rbuf_readl(priv, new_offset); - /* clear if overflowed */ - if (val == ~0) - bcmgenet_rbuf_writel(priv, 0, new_offset); - break; - default: - val = bcmgenet_umac_readl(priv, offset); - /* clear if overflowed */ - if (val == ~0) - bcmgenet_umac_writel(priv, 0, offset); - break; - } - - return val; -} - static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv) { int i, j = 0; @@ -876,28 +836,19 @@ static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv) case BCMGENET_STAT_NETDEV: case BCMGENET_STAT_SOFT: continue; - case BCMGENET_STAT_RUNT: - offset += BCMGENET_STAT_OFFSET; - /* fall through */ - case BCMGENET_STAT_MIB_TX: - offset += BCMGENET_STAT_OFFSET; - /* fall through */ case BCMGENET_STAT_MIB_RX: + case BCMGENET_STAT_MIB_TX: + case BCMGENET_STAT_RUNT: + if (s->type != BCMGENET_STAT_MIB_RX) + offset = BCMGENET_STAT_OFFSET; val = bcmgenet_umac_readl(priv, UMAC_MIB_START + j + offset); - offset = 0; /* Reset Offset */ break; case BCMGENET_STAT_MISC: - if (GENET_IS_V1(priv)) { - val = bcmgenet_umac_readl(priv, s->reg_offset); - /* clear if overflowed */ - if (val == ~0) - bcmgenet_umac_writel(priv, 0, - s->reg_offset); - } else { - val = bcmgenet_update_stat_misc(priv, - s->reg_offset); - } + val = bcmgenet_umac_readl(priv, s->reg_offset); + /* clear if overflowed */ + if (val == ~0) + bcmgenet_umac_writel(priv, 0, s->reg_offset); break; } @@ -1217,7 +1168,6 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, struct bcmgenet_tx_ring *ring) { struct bcmgenet_priv *priv = netdev_priv(dev); - struct device *kdev = &priv->pdev->dev; struct enet_cb *tx_cb_ptr; struct netdev_queue *txq; unsigned int pkts_compl = 0; @@ -1245,7 +1195,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, pkts_compl++; dev->stats.tx_packets++; dev->stats.tx_bytes += tx_cb_ptr->skb->len; - dma_unmap_single(kdev, + dma_unmap_single(&dev->dev, dma_unmap_addr(tx_cb_ptr, dma_addr), dma_unmap_len(tx_cb_ptr, dma_len), DMA_TO_DEVICE); @@ -1253,7 +1203,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, } else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) { dev->stats.tx_bytes += dma_unmap_len(tx_cb_ptr, dma_len); - dma_unmap_page(kdev, + dma_unmap_page(&dev->dev, dma_unmap_addr(tx_cb_ptr, dma_addr), dma_unmap_len(tx_cb_ptr, dma_len), DMA_TO_DEVICE); @@ -1804,7 +1754,6 @@ static int bcmgenet_alloc_rx_buffers(struct bcmgenet_priv *priv, static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv) { - struct device *kdev = &priv->pdev->dev; struct enet_cb *cb; int i; @@ -1812,7 +1761,7 @@ static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv) cb = &priv->rx_cbs[i]; if (dma_unmap_addr(cb, dma_addr)) { - dma_unmap_single(kdev, + dma_unmap_single(&priv->dev->dev, dma_unmap_addr(cb, dma_addr), priv->rx_buf_len, DMA_FROM_DEVICE); dma_unmap_addr_set(cb, dma_addr, 0); @@ -2950,8 +2899,6 @@ static int bcmgenet_open(struct net_device *dev) err_fini_dma: bcmgenet_fini_dma(priv); err_clk_disable: - if (priv->internal_phy) - bcmgenet_power_down(priv, GENET_POWER_PASSIVE); clk_disable_unprepare(priv->clk); return ret; } @@ -3328,12 +3275,6 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv) */ gphy_rev = reg & 0xffff; - /* This is reserved so should require special treatment */ - if (gphy_rev == 0 || gphy_rev == 0x01ff) { - pr_warn("Invalid GPHY revision detected: 0x%04x\n", gphy_rev); - return; - } - /* This is the good old scheme, just GPHY major, no minor nor patch */ if ((gphy_rev & 0xf0) != 0) priv->gphy_rev = gphy_rev << 8; @@ -3342,6 +3283,12 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv) else if ((gphy_rev & 0xff00) != 0) priv->gphy_rev = gphy_rev; + /* This is reserved so should require special treatment */ + else if (gphy_rev == 0 || gphy_rev == 0x01ff) { + pr_warn("Invalid GPHY revision detected: 0x%04x\n", gphy_rev); + return; + } + #ifdef CONFIG_PHYS_ADDR_T_64BIT if (!(params->flags & GENET_HAS_40BITS)) pr_warn("GENET does not support 40-bits PA\n"); @@ -3384,7 +3331,6 @@ static int bcmgenet_probe(struct platform_device *pdev) const void *macaddr; struct resource *r; int err = -EIO; - const char *phy_mode_str; /* Up to GENET_MAX_MQ_CNT + 1 TX queues and RX queues */ dev = alloc_etherdev_mqs(sizeof(*priv), GENET_MAX_MQ_CNT + 1, @@ -3490,13 +3436,6 @@ static int bcmgenet_probe(struct platform_device *pdev) priv->clk_eee = NULL; } - /* If this is an internal GPHY, power it on now, before UniMAC is - * brought out of reset as absolutely no UniMAC activity is allowed - */ - if (dn && !of_property_read_string(dn, "phy-mode", &phy_mode_str) && - !strcasecmp(phy_mode_str, "internal")) - bcmgenet_power_up(priv, GENET_POWER_PASSIVE); - err = reset_umac(priv); if (err) goto err_clk_disable; @@ -3554,8 +3493,7 @@ static int bcmgenet_suspend(struct device *d) bcmgenet_netif_stop(dev); - if (!device_may_wakeup(d)) - phy_suspend(priv->phydev); + phy_suspend(priv->phydev); netif_device_detach(dev); @@ -3652,8 +3590,7 @@ static int bcmgenet_resume(struct device *d) netif_device_attach(dev); - if (!device_may_wakeup(d)) - phy_resume(priv->phydev); + phy_resume(priv->phydev); if (priv->eee.eee_enabled) bcmgenet_eee_enable_set(dev, true); @@ -3663,8 +3600,6 @@ static int bcmgenet_resume(struct device *d) return 0; out_clk_disable: - if (priv->internal_phy) - bcmgenet_power_down(priv, GENET_POWER_PASSIVE); clk_disable_unprepare(priv->clk); return ret; } diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index cef53f2d9854..967367557309 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017 Broadcom + * Copyright (c) 2014 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -214,9 +214,7 @@ struct bcmgenet_mib_counters { #define MDIO_REG_SHIFT 16 #define MDIO_REG_MASK 0x1F -#define UMAC_RBUF_OVFL_CNT_V1 0x61C -#define RBUF_OVFL_CNT_V2 0x80 -#define RBUF_OVFL_CNT_V3PLUS 0x94 +#define UMAC_RBUF_OVFL_CNT 0x61C #define UMAC_MPD_CTRL 0x620 #define MPD_EN (1 << 0) @@ -226,9 +224,7 @@ struct bcmgenet_mib_counters { #define UMAC_MPD_PW_MS 0x624 #define UMAC_MPD_PW_LS 0x628 -#define UMAC_RBUF_ERR_CNT_V1 0x634 -#define RBUF_ERR_CNT_V2 0x84 -#define RBUF_ERR_CNT_V3PLUS 0x98 +#define UMAC_RBUF_ERR_CNT 0x634 #define UMAC_MDF_ERR_CNT 0x638 #define UMAC_MDF_CTRL 0x650 #define UMAC_MDF_ADDR 0x654 diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index e96d1f95bb47..8bdfe53754ba 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -220,6 +220,20 @@ void bcmgenet_phy_power_set(struct net_device *dev, bool enable) udelay(60); } +static void bcmgenet_internal_phy_setup(struct net_device *dev) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + u32 reg; + + /* Power up PHY */ + bcmgenet_phy_power_set(dev, true); + /* enable APD */ + reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT); + reg |= EXT_PWR_DN_EN_LD; + bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT); + bcmgenet_mii_reset(dev); +} + static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv) { u32 reg; @@ -267,6 +281,7 @@ int bcmgenet_mii_config(struct net_device *dev) if (priv->internal_phy) { phy_name = "internal PHY"; + bcmgenet_internal_phy_setup(dev); } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) { phy_name = "MoCA"; bcmgenet_moca_phy_setup(priv); diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index ce3a56bea6e6..ca5ac5d6f4e6 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -8722,10 +8722,6 @@ static void tg3_free_consistent(struct tg3 *tp) tg3_mem_rx_release(tp); tg3_mem_tx_release(tp); - /* tp->hw_stats can be referenced safely: - * 1. under rtnl_lock - * 2. or under tp->lock if TG3_FLAG_INIT_COMPLETE is set. - */ if (tp->hw_stats) { dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats), tp->hw_stats, tp->stats_mapping); @@ -9278,15 +9274,6 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_restore_clk(tp); - /* Increase the core clock speed to fix tx timeout issue for 5762 - * with 100Mbps link speed. - */ - if (tg3_asic_rev(tp) == ASIC_REV_5762) { - val = tr32(TG3_CPMU_CLCK_ORIDE_ENABLE); - tw32(TG3_CPMU_CLCK_ORIDE_ENABLE, val | - TG3_CPMU_MAC_ORIDE_ENABLE); - } - /* Reprobe ASF enable state. */ tg3_flag_clear(tp, ENABLE_ASF); tp->phy_flags &= ~(TG3_PHYFLG_1G_ON_VAUX_OK | @@ -10061,16 +10048,6 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy) tw32(GRC_MODE, tp->grc_mode | val); - /* On one of the AMD platform, MRRS is restricted to 4000 because of - * south bridge limitation. As a workaround, Driver is setting MRRS - * to 2048 instead of default 4096. - */ - if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && - tp->pdev->subsystem_device == TG3PCI_SUBDEVICE_ID_DELL_5762) { - val = tr32(TG3PCI_DEV_STATUS_CTRL) & ~MAX_READ_REQ_MASK; - tw32(TG3PCI_DEV_STATUS_CTRL, val | MAX_READ_REQ_SIZE_2048); - } - /* Setup the timer prescalar register. Clock is always 66Mhz. */ val = tr32(GRC_MISC_CFG); val &= ~0xff; @@ -12054,7 +12031,7 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, int ret; u32 offset, len, b_offset, odd_len; u8 *buf; - __be32 start = 0, end; + __be32 start, end; if (tg3_flag(tp, NO_NVRAM) || eeprom->magic != TG3_EEPROM_MAGIC) @@ -14173,7 +14150,7 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, struct tg3 *tp = netdev_priv(dev); spin_lock_bh(&tp->lock); - if (!tp->hw_stats || !tg3_flag(tp, INIT_COMPLETE)) { + if (!tp->hw_stats) { *stats = tp->net_stats_prev; spin_unlock_bh(&tp->lock); return stats; @@ -14248,10 +14225,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) /* Reset PHY, otherwise the read DMA engine will be in a mode that * breaks all requests to 256 bytes. */ - if (tg3_asic_rev(tp) == ASIC_REV_57766 || - tg3_asic_rev(tp) == ASIC_REV_5717 || - tg3_asic_rev(tp) == ASIC_REV_5719 || - tg3_asic_rev(tp) == ASIC_REV_5720) + if (tg3_asic_rev(tp) == ASIC_REV_57766) reset_phy = true; err = tg3_restart_hw(tp, reset_phy); @@ -18168,14 +18142,14 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, rtnl_lock(); - /* We probably don't have netdev yet */ - if (!netdev || !netif_running(netdev)) - goto done; - /* We needn't recover from permanent error */ if (state == pci_channel_io_frozen) tp->pcierr_recovery = true; + /* We probably don't have netdev yet */ + if (!netdev || !netif_running(netdev)) + goto done; + tg3_phy_stop(tp); tg3_netif_stop(tp); @@ -18272,7 +18246,7 @@ static void tg3_io_resume(struct pci_dev *pdev) rtnl_lock(); - if (!netdev || !netif_running(netdev)) + if (!netif_running(netdev)) goto done; tg3_full_lock(tp, 0); diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 19532961e173..31c9f8295953 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -95,7 +95,6 @@ #define TG3PCI_SUBDEVICE_ID_DELL_JAGUAR 0x0106 #define TG3PCI_SUBDEVICE_ID_DELL_MERLOT 0x0109 #define TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT 0x010a -#define TG3PCI_SUBDEVICE_ID_DELL_5762 0x07f0 #define TG3PCI_SUBVENDOR_ID_COMPAQ PCI_VENDOR_ID_COMPAQ #define TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE 0x007c #define TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2 0x009a @@ -281,9 +280,6 @@ #define TG3PCI_STD_RING_PROD_IDX 0x00000098 /* 64-bit */ #define TG3PCI_RCV_RET_RING_CON_IDX 0x000000a0 /* 64-bit */ /* 0xa8 --> 0xb8 unused */ -#define TG3PCI_DEV_STATUS_CTRL 0x000000b4 -#define MAX_READ_REQ_SIZE_2048 0x00004000 -#define MAX_READ_REQ_MASK 0x00007000 #define TG3PCI_DUAL_MAC_CTRL 0x000000b8 #define DUAL_MAC_CTRL_CH_MASK 0x00000003 #define DUAL_MAC_CTRL_ID 0x00000004 diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c index a36e38676640..9e59663a6ead 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c @@ -1930,13 +1930,13 @@ static void bfa_ioc_send_enable(struct bfa_ioc *ioc) { struct bfi_ioc_ctrl_req enable_req; + struct timeval tv; bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ, bfa_ioc_portid(ioc)); enable_req.clscode = htons(ioc->clscode); - enable_req.rsvd = htons(0); - /* overflow in 2106 */ - enable_req.tv_sec = ntohl(ktime_get_real_seconds()); + do_gettimeofday(&tv); + enable_req.tv_sec = ntohl(tv.tv_sec); bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req)); } @@ -1947,10 +1947,6 @@ bfa_ioc_send_disable(struct bfa_ioc *ioc) bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ, bfa_ioc_portid(ioc)); - disable_req.clscode = htons(ioc->clscode); - disable_req.rsvd = htons(0); - /* overflow in 2106 */ - disable_req.tv_sec = ntohl(ktime_get_real_seconds()); bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req)); } @@ -2845,7 +2841,7 @@ bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver) static void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer) { - strncpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); + memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); } static void diff --git a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c index a4ad782007ce..8fc246ea1fb8 100644 --- a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c +++ b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c @@ -324,7 +324,7 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf, return PTR_ERR(kern_buf); rc = sscanf(kern_buf, "%x:%x", &addr, &len); - if (rc < 2 || len > UINT_MAX >> 2) { + if (rc < 2) { netdev_warn(bnad->netdev, "failed to read user buffer\n"); kfree(kern_buf); return -EINVAL; diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 8d54e7b41bbf..169059c92f80 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -2405,9 +2405,9 @@ static int macb_init(struct platform_device *pdev) if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII) val = GEM_BIT(RGMII); else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII && - (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII)) + (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII)) val = MACB_BIT(RMII); - else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII)) + else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII)) val = MACB_BIT(MII); if (bp->caps & MACB_CAPS_USRIO_HAS_CLKEN) @@ -2738,7 +2738,7 @@ static int at91ether_init(struct platform_device *pdev) } static const struct macb_config at91sam9260_config = { - .caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII, + .caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII, .clk_init = macb_clk_init, .init = macb_init, }; @@ -2751,22 +2751,21 @@ static const struct macb_config pc302gem_config = { }; static const struct macb_config sama5d2_config = { - .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII, + .caps = 0, .dma_burst_length = 16, .clk_init = macb_clk_init, .init = macb_init, }; static const struct macb_config sama5d3_config = { - .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE - | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII, + .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE, .dma_burst_length = 16, .clk_init = macb_clk_init, .init = macb_init, }; static const struct macb_config sama5d4_config = { - .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII, + .caps = 0, .dma_burst_length = 4, .clk_init = macb_clk_init, .init = macb_init, diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 3f385ab94988..d83b0db77821 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -398,7 +398,7 @@ /* Capability mask bits */ #define MACB_CAPS_ISR_CLEAR_ON_WRITE 0x00000001 #define MACB_CAPS_USRIO_HAS_CLKEN 0x00000002 -#define MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII 0x00000004 +#define MACB_CAPS_USRIO_DEFAULT_IS_MII 0x00000004 #define MACB_CAPS_NO_GIGABIT_HALF 0x00000008 #define MACB_CAPS_FIFO_MODE 0x10000000 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000 diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index 50747573f42e..b89504405b72 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -2526,7 +2526,7 @@ static void handle_timestamp(struct octeon_device *oct, octeon_swap_8B_data(&resp->timestamp, 1); - if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) != 0)) { + if (unlikely((skb_shinfo(skb)->tx_flags | SKBTX_IN_PROGRESS) != 0)) { struct skb_shared_hwtstamps ts; u64 ns = resp->timestamp; @@ -2894,7 +2894,7 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) else status = octnet_send_nic_data_pkt(oct, &ndata, xmit_more); if (status == IQ_SEND_FAILED) - goto lio_xmit_dma_failed; + goto lio_xmit_failed; netif_info(lio, tx_queued, lio->netdev, "Transmit queued successfully\n"); @@ -2908,13 +2908,12 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; -lio_xmit_dma_failed: - dma_unmap_single(&oct->pci_dev->dev, ndata.cmd.dptr, - ndata.datasize, DMA_TO_DEVICE); lio_xmit_failed: stats->tx_dropped++; netif_info(lio, tx_err, lio->netdev, "IQ%d Transmit dropped:%llu\n", iq_no, stats->tx_dropped); + dma_unmap_single(&oct->pci_dev->dev, ndata.cmd.dptr, + ndata.datasize, DMA_TO_DEVICE); recv_buffer_free(skb); return NETDEV_TX_OK; } diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h index 22471d283a95..39ca6744a4e6 100644 --- a/drivers/net/ethernet/cavium/thunder/nic.h +++ b/drivers/net/ethernet/cavium/thunder/nic.h @@ -116,15 +116,6 @@ #define NIC_PF_INTR_ID_MBOX0 8 #define NIC_PF_INTR_ID_MBOX1 9 -/* Minimum FIFO level before all packets for the CQ are dropped - * - * This value ensures that once a packet has been "accepted" - * for reception it will not get dropped due to non-availability - * of CQ descriptor. An errata in HW mandates this value to be - * atleast 0x100. - */ -#define NICPF_CQM_MIN_DROP_LEVEL 0x100 - /* Global timer for CQ timer thresh interrupts * Calculated for SCLK of 700Mhz * value written should be a 1/16th of what is expected diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c index 16baaafed26c..5f24d11cb16a 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_main.c +++ b/drivers/net/ethernet/cavium/thunder/nic_main.c @@ -309,7 +309,6 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic) static void nic_init_hw(struct nicpf *nic) { int i; - u64 cqm_cfg; /* Enable NIC HW block */ nic_reg_write(nic, NIC_PF_CFG, 0x3); @@ -346,11 +345,6 @@ static void nic_init_hw(struct nicpf *nic) /* Enable VLAN ethertype matching and stripping */ nic_reg_write(nic, NIC_PF_RX_ETYPE_0_7, (2 << 19) | (ETYPE_ALG_VLAN_STRIP << 16) | ETH_P_8021Q); - - /* Check if HW expected value is higher (could be in future chips) */ - cqm_cfg = nic_reg_read(nic, NIC_PF_CQM_CFG); - if (cqm_cfg < NICPF_CQM_MIN_DROP_LEVEL) - nic_reg_write(nic, NIC_PF_CQM_CFG, NICPF_CQM_MIN_DROP_LEVEL); } /* Channel parse index configuration */ diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h index fab35a593898..dd536be20193 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_reg.h +++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h @@ -21,7 +21,7 @@ #define NIC_PF_TCP_TIMER (0x0060) #define NIC_PF_BP_CFG (0x0080) #define NIC_PF_RRM_CFG (0x0088) -#define NIC_PF_CQM_CFG (0x00A0) +#define NIC_PF_CQM_CF (0x00A0) #define NIC_PF_CNM_CF (0x00A8) #define NIC_PF_CNM_STATUS (0x00B0) #define NIC_PF_CQ_AVG_CFG (0x00C0) @@ -170,6 +170,7 @@ #define NIC_QSET_SQ_0_7_DOOR (0x010838) #define NIC_QSET_SQ_0_7_STATUS (0x010840) #define NIC_QSET_SQ_0_7_DEBUG (0x010848) +#define NIC_QSET_SQ_0_7_CNM_CHG (0x010860) #define NIC_QSET_SQ_0_7_STAT_0_1 (0x010900) #define NIC_QSET_RBDR_0_1_CFG (0x010C00) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c index ff1d777f3ed9..a12b2e38cf61 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c @@ -380,10 +380,7 @@ static void nicvf_get_regs(struct net_device *dev, p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DOOR, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DEBUG, q); - /* Padding, was NIC_QSET_SQ_0_7_CNM_CHG, which - * produces bus errors when read - */ - p[i++] = 0; + p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CNM_CHG, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STAT_0_1, q); reg_offset = NIC_QSET_SQ_0_7_STAT_0_1 | (1 << 3); p[i++] = nicvf_queue_reg_read(nic, reg_offset, q); diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index b7093b9cd1e8..dde8dc720cd3 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -566,7 +566,8 @@ static inline void nicvf_set_rxhash(struct net_device *netdev, static void nicvf_rcv_pkt_handler(struct net_device *netdev, struct napi_struct *napi, - struct cqe_rx_t *cqe_rx) + struct cmp_queue *cq, + struct cqe_rx_t *cqe_rx, int cqe_type) { struct sk_buff *skb; struct nicvf *nic = netdev_priv(netdev); @@ -582,7 +583,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev, } /* Check for errors */ - err = nicvf_check_cqe_rx_errs(nic, cqe_rx); + err = nicvf_check_cqe_rx_errs(nic, cq, cqe_rx); if (err && !cqe_rx->rb_cnt) return; @@ -673,7 +674,8 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx, cq_idx, cq_desc->cqe_type); switch (cq_desc->cqe_type) { case CQE_TYPE_RX: - nicvf_rcv_pkt_handler(netdev, napi, cq_desc); + nicvf_rcv_pkt_handler(netdev, napi, cq, + cq_desc, CQE_TYPE_RX); work_done++; break; case CQE_TYPE_SEND: @@ -1115,6 +1117,7 @@ int nicvf_stop(struct net_device *netdev) /* Clear multiqset info */ nic->pnicvf = nic; + nic->sqs_count = 0; return 0; } @@ -1343,9 +1346,6 @@ void nicvf_update_stats(struct nicvf *nic) drv_stats->tx_frames_ok = stats->tx_ucast_frames_ok + stats->tx_bcast_frames_ok + stats->tx_mcast_frames_ok; - drv_stats->rx_frames_ok = stats->rx_ucast_frames + - stats->rx_bcast_frames + - stats->rx_mcast_frames; drv_stats->rx_drops = stats->rx_drop_red + stats->rx_drop_overrun; drv_stats->tx_drops = stats->tx_drops; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index 912ee28ab58b..d1c217eaf417 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -1414,12 +1414,16 @@ void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx) } /* Check for errors in the receive cmp.queue entry */ -int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx) +int nicvf_check_cqe_rx_errs(struct nicvf *nic, + struct cmp_queue *cq, struct cqe_rx_t *cqe_rx) { struct nicvf_hw_stats *stats = &nic->hw_stats; + struct nicvf_drv_stats *drv_stats = &nic->drv_stats; - if (!cqe_rx->err_level && !cqe_rx->err_opcode) + if (!cqe_rx->err_level && !cqe_rx->err_opcode) { + drv_stats->rx_frames_ok++; return 0; + } if (netif_msg_rx_err(nic)) netdev_err(nic->netdev, diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h index 5652c612e20b..033e8306e91c 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h @@ -344,7 +344,8 @@ u64 nicvf_queue_reg_read(struct nicvf *nic, /* Stats */ void nicvf_update_rq_stats(struct nicvf *nic, int rq_idx); void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx); -int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx); +int nicvf_check_cqe_rx_errs(struct nicvf *nic, + struct cmp_queue *cq, struct cqe_rx_t *cqe_rx); int nicvf_check_cqe_tx_errs(struct nicvf *nic, struct cmp_queue *cq, struct cqe_send_t *cqe_tx); #endif /* NICVF_QUEUES_H */ diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index 42718cc7d4e8..9df26c2263bc 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -549,9 +549,7 @@ static int bgx_xaui_check_link(struct lmac *lmac) } /* Clear rcvflt bit (latching high) and read it back */ - if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT) - bgx_reg_modify(bgx, lmacid, - BGX_SPUX_STATUS2, SPU_STATUS2_RCVFLT); + bgx_reg_modify(bgx, lmacid, BGX_SPUX_STATUS2, SPU_STATUS2_RCVFLT); if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT) { dev_err(&bgx->pdev->dev, "Receive fault, retry training\n"); if (bgx->use_training) { @@ -570,6 +568,13 @@ static int bgx_xaui_check_link(struct lmac *lmac) return -1; } + /* Wait for MAC RX to be ready */ + if (bgx_poll_reg(bgx, lmacid, BGX_SMUX_RX_CTL, + SMU_RX_CTL_STATUS, true)) { + dev_err(&bgx->pdev->dev, "SMU RX link not okay\n"); + return -1; + } + /* Wait for BGX RX to be idle */ if (bgx_poll_reg(bgx, lmacid, BGX_SMUX_CTL, SMU_CTL_RX_IDLE, false)) { dev_err(&bgx->pdev->dev, "SMU RX not idle\n"); @@ -582,30 +587,29 @@ static int bgx_xaui_check_link(struct lmac *lmac) return -1; } - /* Clear receive packet disable */ + if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT) { + dev_err(&bgx->pdev->dev, "Receive fault\n"); + return -1; + } + + /* Receive link is latching low. Force it high and verify it */ + bgx_reg_modify(bgx, lmacid, BGX_SPUX_STATUS1, SPU_STATUS1_RCV_LNK); + if (bgx_poll_reg(bgx, lmacid, BGX_SPUX_STATUS1, + SPU_STATUS1_RCV_LNK, false)) { + dev_err(&bgx->pdev->dev, "SPU receive link down\n"); + return -1; + } + cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_MISC_CONTROL); cfg &= ~SPU_MISC_CTL_RX_DIS; bgx_reg_write(bgx, lmacid, BGX_SPUX_MISC_CONTROL, cfg); - - /* Check for MAC RX faults */ - cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_RX_CTL); - /* 0 - Link is okay, 1 - Local fault, 2 - Remote fault */ - cfg &= SMU_RX_CTL_STATUS; - if (!cfg) - return 0; - - /* Rx local/remote fault seen. - * Do lmac reinit to see if condition recovers - */ - bgx_lmac_xaui_init(bgx, lmacid, bgx->lmac_type); - - return -1; + return 0; } static void bgx_poll_for_link(struct work_struct *work) { struct lmac *lmac; - u64 spu_link, smu_link; + u64 link; lmac = container_of(work, struct lmac, dwork.work); @@ -615,11 +619,8 @@ static void bgx_poll_for_link(struct work_struct *work) bgx_poll_reg(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1, SPU_STATUS1_RCV_LNK, false); - spu_link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1); - smu_link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SMUX_RX_CTL); - - if ((spu_link & SPU_STATUS1_RCV_LNK) && - !(smu_link & SMU_RX_CTL_STATUS)) { + link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1); + if (link & SPU_STATUS1_RCV_LNK) { lmac->link_up = 1; if (lmac->bgx->lmac_type == BGX_MODE_XLAUI) lmac->last_speed = 40000; @@ -633,15 +634,9 @@ static void bgx_poll_for_link(struct work_struct *work) } if (lmac->last_link != lmac->link_up) { - if (lmac->link_up) { - if (bgx_xaui_check_link(lmac)) { - /* Errors, clear link_up state */ - lmac->link_up = 0; - lmac->last_speed = SPEED_UNKNOWN; - lmac->last_duplex = DUPLEX_UNKNOWN; - } - } lmac->last_link = lmac->link_up; + if (lmac->link_up) + bgx_xaui_check_link(lmac); } queue_delayed_work(lmac->check_link, &lmac->dwork, HZ * 2); @@ -713,7 +708,7 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid) static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid) { struct lmac *lmac; - u64 cfg; + u64 cmrx_cfg; lmac = &bgx->lmac[lmacid]; if (lmac->check_link) { @@ -722,33 +717,9 @@ static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid) destroy_workqueue(lmac->check_link); } - /* Disable packet reception */ - cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG); - cfg &= ~CMR_PKT_RX_EN; - bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg); - - /* Give chance for Rx/Tx FIFO to get drained */ - bgx_poll_reg(bgx, lmacid, BGX_CMRX_RX_FIFO_LEN, (u64)0x1FFF, true); - bgx_poll_reg(bgx, lmacid, BGX_CMRX_TX_FIFO_LEN, (u64)0x3FFF, true); - - /* Disable packet transmission */ - cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG); - cfg &= ~CMR_PKT_TX_EN; - bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg); - - /* Disable serdes lanes */ - if (!lmac->is_sgmii) - bgx_reg_modify(bgx, lmacid, - BGX_SPUX_CONTROL1, SPU_CTL_LOW_POWER); - else - bgx_reg_modify(bgx, lmacid, - BGX_GMP_PCS_MRX_CTL, PCS_MRX_CTL_PWR_DN); - - /* Disable LMAC */ - cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG); - cfg &= ~CMR_EN; - bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg); - + cmrx_cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG); + cmrx_cfg &= ~(1 << 15); + bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cmrx_cfg); bgx_flush_dmac_addrs(bgx, lmacid); if ((bgx->lmac_type != BGX_MODE_XFI) && diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h index 42010d2e5ddf..149e179363a1 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h @@ -41,7 +41,6 @@ #define BGX_CMRX_RX_STAT10 0xC0 #define BGX_CMRX_RX_BP_DROP 0xC8 #define BGX_CMRX_RX_DMAC_CTL 0x0E8 -#define BGX_CMRX_RX_FIFO_LEN 0x108 #define BGX_CMR_RX_DMACX_CAM 0x200 #define RX_DMACX_CAM_EN BIT_ULL(48) #define RX_DMACX_CAM_LMACID(x) (x << 49) @@ -51,7 +50,6 @@ #define BGX_CMR_CHAN_MSK_AND 0x450 #define BGX_CMR_BIST_STATUS 0x460 #define BGX_CMR_RX_LMACS 0x468 -#define BGX_CMRX_TX_FIFO_LEN 0x518 #define BGX_CMRX_TX_STAT0 0x600 #define BGX_CMRX_TX_STAT1 0x608 #define BGX_CMRX_TX_STAT2 0x610 diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index 7ae8374bff13..8f7aa53a4c4b 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include "common.h" @@ -2257,7 +2256,6 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) if (t.qset_idx >= nqsets) return -EINVAL; - t.qset_idx = array_index_nospec(t.qset_idx, nqsets); q = &adapter->params.sge.qset[q1 + t.qset_idx]; t.rspq_size = q->rspq_size; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index a3e1498ca67c..0d147610a06f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -338,7 +338,7 @@ static void dcb_tx_queue_prio_enable(struct net_device *dev, int enable) "Can't %s DCB Priority on port %d, TX Queue %d: err=%d\n", enable ? "set" : "unset", pi->port_id, i, -err); else - txq->dcb_prio = enable ? value : 0; + txq->dcb_prio = value; } } #endif /* CONFIG_CHELSIO_T4_DCB */ @@ -2714,14 +2714,10 @@ static int cxgb_up(struct adapter *adap) if (err) goto irq_err; } - - mutex_lock(&uld_mutex); enable_rx(adap); t4_sge_start(adap); t4_intr_enable(adap); adap->flags |= FULL_INIT_DONE; - mutex_unlock(&uld_mutex); - notify_ulds(adap, CXGB4_STATE_UP); #if IS_ENABLED(CONFIG_IPV6) update_clip(adap); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index de23f23b41de..cf61a5869c6e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -6076,18 +6076,13 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox, if (!t4_fw_matches_chip(adap, fw_hdr)) return -EINVAL; - /* Disable FW_OK flag so that mbox commands with FW_OK flag set - * wont be sent when we are flashing FW. - */ - adap->flags &= ~FW_OK; - ret = t4_fw_halt(adap, mbox, force); if (ret < 0 && !force) - goto out; + return ret; ret = t4_load_fw(adap, fw_data, size); if (ret < 0) - goto out; + return ret; /* * Older versions of the firmware don't understand the new @@ -6098,17 +6093,7 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox, * its header flags to see if it advertises the capability. */ reset = ((be32_to_cpu(fw_hdr->flags) & FW_HDR_FLAGS_RESET_HALT) == 0); - ret = t4_fw_restart(adap, mbox, reset); - - /* Grab potentially new Firmware Device Log parameters so we can see - * how healthy the new Firmware is. It's okay to contact the new - * Firmware for these parameters even though, as far as it's - * concerned, we've never said "HELLO" to it ... - */ - (void)t4_init_devlog_params(adap); -out: - adap->flags |= FW_OK; - return ret; + return t4_fw_restart(adap, mbox, reset); } /** @@ -7711,16 +7696,7 @@ int t4_cim_read_la(struct adapter *adap, u32 *la_buf, unsigned int *wrptr) ret = t4_cim_read(adap, UP_UP_DBG_LA_DATA_A, 1, &la_buf[i]); if (ret) break; - - /* Bits 0-3 of UpDbgLaRdPtr can be between 0000 to 1001 to - * identify the 32-bit portion of the full 312-bit data - */ - if (is_t6(adap->params.chip) && (idx & 0xf) >= 9) - idx = (idx & 0xff0) + 0x10; - else - idx++; - /* address can't exceed 0xfff */ - idx &= UPDBGLARDPTR_M; + idx = (idx + 1) & UPDBGLARDPTR_M; } restart: if (cfg & UPDBGLAEN_F) { diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index ec8ffd7eae33..fa3786a9d30e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c @@ -2604,8 +2604,8 @@ void t4vf_sge_stop(struct adapter *adapter) int t4vf_sge_init(struct adapter *adapter) { struct sge_params *sge_params = &adapter->params.sge; - u32 fl_small_pg = sge_params->sge_fl_buffer_size[0]; - u32 fl_large_pg = sge_params->sge_fl_buffer_size[1]; + u32 fl0 = sge_params->sge_fl_buffer_size[0]; + u32 fl1 = sge_params->sge_fl_buffer_size[1]; struct sge *s = &adapter->sge; unsigned int ingpadboundary, ingpackboundary; @@ -2614,20 +2614,9 @@ int t4vf_sge_init(struct adapter *adapter) * the Physical Function Driver. Ideally we should be able to deal * with _any_ configuration. Practice is different ... */ - - /* We only bother using the Large Page logic if the Large Page Buffer - * is larger than our Page Size Buffer. - */ - if (fl_large_pg <= fl_small_pg) - fl_large_pg = 0; - - /* The Page Size Buffer must be exactly equal to our Page Size and the - * Large Page Size Buffer should be 0 (per above) or a power of 2. - */ - if (fl_small_pg != PAGE_SIZE || - (fl_large_pg & (fl_large_pg - 1)) != 0) { + if (fl0 != PAGE_SIZE || (fl1 != 0 && fl1 <= fl0)) { dev_err(adapter->pdev_dev, "bad SGE FL buffer sizes [%d, %d]\n", - fl_small_pg, fl_large_pg); + fl0, fl1); return -EINVAL; } if ((sge_params->sge_control & RXPKTCPLMODE_F) == 0) { @@ -2638,8 +2627,8 @@ int t4vf_sge_init(struct adapter *adapter) /* * Now translate the adapter parameters into our internal forms. */ - if (fl_large_pg) - s->fl_pg_order = ilog2(fl_large_pg) - PAGE_SHIFT; + if (fl1) + s->fl_pg_order = ilog2(fl1) - PAGE_SHIFT; s->stat_len = ((sge_params->sge_control & EGRSTATUSPAGESIZE_F) ? 128 : 64); s->pktshift = PKTSHIFT_G(sge_params->sge_control); diff --git a/drivers/net/ethernet/cirrus/Kconfig b/drivers/net/ethernet/cirrus/Kconfig index ec0b545197e2..5ab912937aff 100644 --- a/drivers/net/ethernet/cirrus/Kconfig +++ b/drivers/net/ethernet/cirrus/Kconfig @@ -19,7 +19,6 @@ if NET_VENDOR_CIRRUS config CS89x0 tristate "CS89x0 support" depends on ISA || EISA || ARM - depends on !PPC32 ---help--- Support for CS89x0 chipset based Ethernet cards. If you have a network (Ethernet) card of this type, say Y and read the file diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.c b/drivers/net/ethernet/cisco/enic/enic_clsf.c index 4d9014d5b36d..3c677ed3c29e 100644 --- a/drivers/net/ethernet/cisco/enic/enic_clsf.c +++ b/drivers/net/ethernet/cisco/enic/enic_clsf.c @@ -78,6 +78,7 @@ void enic_rfs_flw_tbl_init(struct enic *enic) enic->rfs_h.max = enic->config.num_arfs; enic->rfs_h.free = enic->rfs_h.max; enic->rfs_h.toclean = 0; + enic_rfs_timer_start(enic); } void enic_rfs_flw_tbl_free(struct enic *enic) @@ -86,6 +87,7 @@ void enic_rfs_flw_tbl_free(struct enic *enic) enic_rfs_timer_stop(enic); spin_lock_bh(&enic->rfs_h.lock); + enic->rfs_h.free = 0; for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) { struct hlist_head *hhead; struct hlist_node *tmp; @@ -96,7 +98,6 @@ void enic_rfs_flw_tbl_free(struct enic *enic) enic_delfltr(enic, n->fltr_id); hlist_del(&n->node); kfree(n); - enic->rfs_h.free++; } } spin_unlock_bh(&enic->rfs_h.lock); diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index b20bce2c7da1..b36643ef0593 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1726,8 +1726,6 @@ static int enic_open(struct net_device *netdev) } for (i = 0; i < enic->rq_count; i++) { - /* enable rq before updating rq desc */ - vnic_rq_enable(&enic->rq[i]); vnic_rq_fill(&enic->rq[i], enic_rq_alloc_buf); /* Need at least one buffer on ring to get going */ if (vnic_rq_desc_used(&enic->rq[i]) == 0) { @@ -1739,6 +1737,8 @@ static int enic_open(struct net_device *netdev) for (i = 0; i < enic->wq_count; i++) vnic_wq_enable(&enic->wq[i]); + for (i = 0; i < enic->rq_count; i++) + vnic_rq_enable(&enic->rq[i]); if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) enic_dev_add_station_addr(enic); @@ -1760,17 +1760,13 @@ static int enic_open(struct net_device *netdev) vnic_intr_unmask(&enic->intr[i]); enic_notify_timer_start(enic); - enic_rfs_timer_start(enic); + enic_rfs_flw_tbl_init(enic); return 0; err_out_free_rq: - for (i = 0; i < enic->rq_count; i++) { - err = vnic_rq_disable(&enic->rq[i]); - if (err) - return err; + for (i = 0; i < enic->rq_count; i++) vnic_rq_clean(&enic->rq[i], enic_free_rq_buf); - } enic_dev_notify_unset(enic); err_out_free_intr: enic_unset_affinity_hint(enic); @@ -1842,32 +1838,10 @@ static int enic_stop(struct net_device *netdev) return 0; } -static int _enic_change_mtu(struct net_device *netdev, int new_mtu) -{ - bool running = netif_running(netdev); - int err = 0; - - ASSERT_RTNL(); - if (running) { - err = enic_stop(netdev); - if (err) - return err; - } - - netdev->mtu = new_mtu; - - if (running) { - err = enic_open(netdev); - if (err) - return err; - } - - return 0; -} - static int enic_change_mtu(struct net_device *netdev, int new_mtu) { struct enic *enic = netdev_priv(netdev); + int running = netif_running(netdev); if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU) return -EINVAL; @@ -1875,12 +1849,20 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu) if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) return -EOPNOTSUPP; + if (running) + enic_stop(netdev); + + netdev->mtu = new_mtu; + if (netdev->mtu > enic->port_mtu) netdev_warn(netdev, - "interface MTU (%d) set higher than port MTU (%d)\n", - netdev->mtu, enic->port_mtu); + "interface MTU (%d) set higher than port MTU (%d)\n", + netdev->mtu, enic->port_mtu); + + if (running) + enic_open(netdev); - return _enic_change_mtu(netdev, new_mtu); + return 0; } static void enic_change_mtu_work(struct work_struct *work) @@ -1888,9 +1870,47 @@ static void enic_change_mtu_work(struct work_struct *work) struct enic *enic = container_of(work, struct enic, change_mtu_work); struct net_device *netdev = enic->netdev; int new_mtu = vnic_dev_mtu(enic->vdev); + int err; + unsigned int i; + + new_mtu = max_t(int, ENIC_MIN_MTU, min_t(int, ENIC_MAX_MTU, new_mtu)); rtnl_lock(); - (void)_enic_change_mtu(netdev, new_mtu); + + /* Stop RQ */ + del_timer_sync(&enic->notify_timer); + + for (i = 0; i < enic->rq_count; i++) + napi_disable(&enic->napi[i]); + + vnic_intr_mask(&enic->intr[0]); + enic_synchronize_irqs(enic); + err = vnic_rq_disable(&enic->rq[0]); + if (err) { + rtnl_unlock(); + netdev_err(netdev, "Unable to disable RQ.\n"); + return; + } + vnic_rq_clean(&enic->rq[0], enic_free_rq_buf); + vnic_cq_clean(&enic->cq[0]); + vnic_intr_clean(&enic->intr[0]); + + /* Fill RQ with new_mtu-sized buffers */ + netdev->mtu = new_mtu; + vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); + /* Need at least one buffer on ring to get going */ + if (vnic_rq_desc_used(&enic->rq[0]) == 0) { + rtnl_unlock(); + netdev_err(netdev, "Unable to alloc receive buffers.\n"); + return; + } + + /* Start RQ */ + vnic_rq_enable(&enic->rq[0]); + napi_enable(&enic->napi[0]); + vnic_intr_unmask(&enic->intr[0]); + enic_notify_timer_start(enic); + rtnl_unlock(); netdev_info(netdev, "interface MTU set as %d\n", netdev->mtu); @@ -2519,11 +2539,11 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); /* Query PCI controller on system for DMA addressing - * limitation for the device. Try 47-bit first, and + * limitation for the device. Try 64-bit first, and * fail to 32-bit. */ - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(47)); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); if (err) { err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { @@ -2537,10 +2557,10 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_release_regions; } } else { - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(47)); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); if (err) { dev_err(dev, "Unable to obtain %u-bit DMA " - "for consistent allocations, aborting\n", 47); + "for consistent allocations, aborting\n", 64); goto err_out_release_regions; } using_dac = 1; @@ -2670,7 +2690,6 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) enic->notify_timer.function = enic_notify_timer; enic->notify_timer.data = (unsigned long)enic; - enic_rfs_flw_tbl_init(enic); enic_set_rx_coal_setting(enic); INIT_WORK(&enic->reset, enic_reset); INIT_WORK(&enic->tx_hang_reset, enic_tx_hang_reset); diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c index 3acde3b9b767..8966f3159bb2 100644 --- a/drivers/net/ethernet/dec/tulip/de4x5.c +++ b/drivers/net/ethernet/dec/tulip/de4x5.c @@ -1990,7 +1990,7 @@ SetMulticastFilter(struct net_device *dev) static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST; -static int de4x5_eisa_probe(struct device *gendev) +static int __init de4x5_eisa_probe (struct device *gendev) { struct eisa_device *edev; u_long iobase; diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 7b8638ddb673..1795c935ff02 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1052,7 +1052,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, err: spin_unlock_bh(&adapter->mcc_lock); - if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST) + if (status == MCC_STATUS_UNAUTHORIZED_REQUEST) status = -EPERM; return status; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 26255862d1cf..8a1d9fffd7d6 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -5260,11 +5260,9 @@ static netdev_features_t be_features_check(struct sk_buff *skb, struct be_adapter *adapter = netdev_priv(dev); u8 l4_hdr = 0; - /* The code below restricts offload features for some tunneled and - * Q-in-Q packets. + /* The code below restricts offload features for some tunneled packets. * Offload features for normal (non tunnel) packets are unchanged. */ - features = vlan_features_check(skb, features); if (!skb->encapsulation || !(adapter->flags & BE_FLAGS_VXLAN_OFFLOADS)) return features; diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 52f2230062e7..ff665493ca97 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -713,8 +713,6 @@ static int ethoc_open(struct net_device *dev) if (ret) return ret; - napi_enable(&priv->napi); - ethoc_init_ring(priv, dev->mem_start); ethoc_reset(priv); @@ -727,6 +725,7 @@ static int ethoc_open(struct net_device *dev) } phy_start(priv->phy); + napi_enable(&priv->napi); if (netif_msg_ifup(priv)) { dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n", diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 58c0fccdd8cb..6d0c5d5eea6d 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c index a3b2e23921bf..b1b9ebafb354 100644 --- a/drivers/net/ethernet/fealnx.c +++ b/drivers/net/ethernet/fealnx.c @@ -257,8 +257,8 @@ enum rx_desc_status_bits { RXFSD = 0x00000800, /* first descriptor */ RXLSD = 0x00000400, /* last descriptor */ ErrorSummary = 0x80, /* error summary */ - RUNTPKT = 0x40, /* runt packet received */ - LONGPKT = 0x20, /* long packet received */ + RUNT = 0x40, /* runt packet received */ + LONG = 0x20, /* long packet received */ FAE = 0x10, /* frame align error */ CRC = 0x08, /* crc error */ RXER = 0x04, /* receive error */ @@ -1633,7 +1633,7 @@ static int netdev_rx(struct net_device *dev) dev->name, rx_status); dev->stats.rx_errors++; /* end of a packet. */ - if (rx_status & (LONGPKT | RUNTPKT)) + if (rx_status & (LONG | RUNT)) dev->stats.rx_length_errors++; if (rx_status & RXER) dev->stats.rx_frame_errors++; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index ae8e4fc22e7b..f6147ffc7fbc 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -944,11 +944,11 @@ fec_restart(struct net_device *ndev) * enet-mac reset will reset mac address registers too, * so need to reconfigure it. */ - memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); - writel((__force u32)cpu_to_be32(temp_mac[0]), - fep->hwp + FEC_ADDR_LOW); - writel((__force u32)cpu_to_be32(temp_mac[1]), - fep->hwp + FEC_ADDR_HIGH); + if (fep->quirks & FEC_QUIRK_ENET_MAC) { + memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); + writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW); + writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); + } /* Clear any outstanding interrupt. */ writel(0xffffffff, fep->hwp + FEC_IEVENT); @@ -2968,7 +2968,6 @@ static void set_multicast_list(struct net_device *ndev) struct netdev_hw_addr *ha; unsigned int i, bit, data, crc, tmp; unsigned char hash; - unsigned int hash_high = 0, hash_low = 0; if (ndev->flags & IFF_PROMISC) { tmp = readl(fep->hwp + FEC_R_CNTRL); @@ -2991,7 +2990,11 @@ static void set_multicast_list(struct net_device *ndev) return; } - /* Add the addresses in hash register */ + /* Clear filter and add the addresses in hash register + */ + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + netdev_for_each_mc_addr(ha, ndev) { /* calculate crc32 value of mac address */ crc = 0xffffffff; @@ -3009,14 +3012,16 @@ static void set_multicast_list(struct net_device *ndev) */ hash = (crc >> (32 - HASH_BITS)) & 0x3f; - if (hash > 31) - hash_high |= 1 << (hash - 32); - else - hash_low |= 1 << hash; + if (hash > 31) { + tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + tmp |= 1 << (hash - 32); + writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + } else { + tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW); + tmp |= 1 << hash; + writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + } } - - writel(hash_high, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - writel(hash_low, fep->hwp + FEC_GRP_HASH_TABLE_LOW); } /* Set a MAC change in hardware. */ @@ -3539,8 +3544,6 @@ fec_drv_remove(struct platform_device *pdev) fec_enet_mii_remove(fep); if (fep->reg_phy) regulator_disable(fep->reg_phy); - pm_runtime_put(&pdev->dev); - pm_runtime_disable(&pdev->dev); of_node_put(fep->phy_node); free_netdev(ndev); diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 9c76f1a2f57b..40071dad1c57 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -382,7 +382,7 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev) { const struct of_device_id *id = of_match_device(fsl_pq_mdio_match, &pdev->dev); - const struct fsl_pq_mdio_data *data; + const struct fsl_pq_mdio_data *data = id->data; struct device_node *np = pdev->dev.of_node; struct resource res; struct device_node *tbi; @@ -390,13 +390,6 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev) struct mii_bus *new_bus; int err; - if (!id) { - dev_err(&pdev->dev, "Failed to match device\n"); - return -ENODEV; - } - - data = id->data; - dev_dbg(&pdev->dev, "found %s compatible node\n", id->compatible); new_bus = mdiobus_alloc_size(sizeof(*priv)); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 2d61369f586f..3e233d924cce 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1375,11 +1375,9 @@ static int gfar_probe(struct platform_device *ofdev) gfar_init_addr_hash_table(priv); - /* Insert receive time stamps into padding alignment bytes, and - * plus 2 bytes padding to ensure the cpu alignment. - */ + /* Insert receive time stamps into padding alignment bytes */ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) - priv->padding = 8 + DEFAULT_PADDING; + priv->padding = 8; if (dev->features & NETIF_F_IP_CSUM || priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) @@ -2001,8 +1999,8 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue) if (!rxb->page) continue; - dma_unmap_page(rx_queue->dev, rxb->dma, - PAGE_SIZE, DMA_FROM_DEVICE); + dma_unmap_single(rx_queue->dev, rxb->dma, + PAGE_SIZE, DMA_FROM_DEVICE); __free_page(rxb->page); rxb->page = NULL; @@ -2941,7 +2939,7 @@ static bool gfar_add_rx_frag(struct gfar_rx_buff *rxb, u32 lstatus, size, GFAR_RXB_TRUESIZE); /* try reuse page */ - if (unlikely(page_count(page) != 1 || page_is_pfmemalloc(page))) + if (unlikely(page_count(page) != 1)) return false; /* change offset to the other half */ @@ -3053,6 +3051,9 @@ static void gfar_process_frame(struct net_device *ndev, struct sk_buff *skb) if (ndev->features & NETIF_F_RXCSUM) gfar_rx_checksum(skb, fcb); + /* Tell the skb what kind of packet this is */ + skb->protocol = eth_type_trans(skb, ndev); + /* There's need to check for NETIF_F_HW_VLAN_CTAG_RX here. * Even if vlan rx accel is disabled, on some chips * RXFCB_VLN is pseudo randomly set. @@ -3123,15 +3124,13 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) continue; } - gfar_process_frame(ndev, skb); - /* Increment the number of packets */ total_pkts++; total_bytes += skb->len; skb_record_rx_queue(skb, rx_queue->qindex); - skb->protocol = eth_type_trans(skb, ndev); + gfar_process_frame(ndev, skb); /* Send the packet up the stack */ napi_gro_receive(&rx_queue->grp->napi_rx, skb); @@ -3677,7 +3676,7 @@ static noinline void gfar_update_link_state(struct gfar_private *priv) u32 tempval1 = gfar_read(®s->maccfg1); u32 tempval = gfar_read(®s->maccfg2); u32 ecntrl = gfar_read(®s->ecntrl); - u32 tx_flow_oldval = (tempval1 & MACCFG1_TX_FLOW); + u32 tx_flow_oldval = (tempval & MACCFG1_TX_FLOW); if (phydev->duplex != priv->oldduplex) { if (!(phydev->duplex)) diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c index d540ee190038..b40fba929d65 100644 --- a/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -314,10 +314,11 @@ static int ptp_gianfar_adjtime(struct ptp_clock_info *ptp, s64 delta) now = tmr_cnt_read(etsects); now += delta; tmr_cnt_write(etsects, now); - set_fipers(etsects); spin_unlock_irqrestore(&etsects->lock, flags); + set_fipers(etsects); + return 0; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index 9ff2881f933d..bdbd80423b17 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -900,7 +900,9 @@ static inline void dsaf_write_reg(void __iomem *base, u32 reg, u32 value) { - writel(value, base + reg); + u8 __iomem *reg_addr = ACCESS_ONCE(base); + + writel(value, reg_addr + reg); } #define dsaf_write_dev(a, reg, value) \ @@ -908,7 +910,9 @@ static inline void dsaf_write_reg(void __iomem *base, u32 reg, u32 value) static inline u32 dsaf_read_reg(u8 __iomem *base, u32 reg) { - return readl(base + reg); + u8 __iomem *reg_addr = ACCESS_ONCE(base); + + return readl(reg_addr + reg); } #define dsaf_read_dev(a, reg) \ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c index b1a27aef4425..802d55457f19 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c @@ -776,7 +776,7 @@ static void hns_xgmac_get_strings(u32 stringset, u8 *data) */ static int hns_xgmac_get_sset_count(int stringset) { - if (stringset == ETH_SS_STATS || stringset == ETH_SS_PRIV_FLAGS) + if (stringset == ETH_SS_STATS) return ARRAY_SIZE(g_xgmac_stats_string); return 0; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 2fa54b0b0679..08cef0dfb5db 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -105,8 +105,8 @@ int hns_nic_net_xmit_hw(struct net_device *ndev, struct hns_nic_ring_data *ring_data) { struct hns_nic_priv *priv = netdev_priv(ndev); + struct device *dev = priv->dev; struct hnae_ring *ring = ring_data->ring; - struct device *dev = ring_to_dev(ring); struct netdev_queue *dev_queue; struct skb_frag_struct *frag; int buf_num; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 4b91eb70c683..a0332129970b 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -1000,10 +1000,8 @@ int hns_get_sset_count(struct net_device *netdev, int stringset) cnt--; return cnt; - } else if (stringset == ETH_SS_STATS) { - return (HNS_NET_STATS_CNT + ops->get_sset_count(h, stringset)); } else { - return -EOPNOTSUPP; + return (HNS_NET_STATS_CNT + ops->get_sset_count(h, stringset)); } } diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c index 3daf2d4a7ca0..ae6e30d39f0f 100644 --- a/drivers/net/ethernet/hp/hp100.c +++ b/drivers/net/ethernet/hp/hp100.c @@ -194,6 +194,7 @@ static const char *hp100_isa_tbl[] = { }; #endif +#ifdef CONFIG_EISA static struct eisa_device_id hp100_eisa_tbl[] = { { "HWPF180" }, /* HP J2577 rev A */ { "HWP1920" }, /* HP 27248B */ @@ -204,7 +205,9 @@ static struct eisa_device_id hp100_eisa_tbl[] = { { "" } /* Mandatory final entry ! */ }; MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl); +#endif +#ifdef CONFIG_PCI static const struct pci_device_id hp100_pci_tbl[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID,}, @@ -216,6 +219,7 @@ static const struct pci_device_id hp100_pci_tbl[] = { {} /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, hp100_pci_tbl); +#endif static int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO; static int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX; @@ -2838,7 +2842,8 @@ static void cleanup_dev(struct net_device *d) free_netdev(d); } -static int hp100_eisa_probe(struct device *gendev) +#ifdef CONFIG_EISA +static int __init hp100_eisa_probe (struct device *gendev) { struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private)); struct eisa_device *edev = to_eisa_device(gendev); @@ -2879,7 +2884,9 @@ static struct eisa_driver hp100_eisa_driver = { .remove = hp100_eisa_remove, } }; +#endif +#ifdef CONFIG_PCI static int hp100_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2948,6 +2955,7 @@ static struct pci_driver hp100_pci_driver = { .probe = hp100_pci_probe, .remove = hp100_pci_remove, }; +#endif /* * module section @@ -3024,17 +3032,23 @@ static int __init hp100_module_init(void) err = hp100_isa_init(); if (err && err != -ENODEV) goto out; +#ifdef CONFIG_EISA err = eisa_driver_register(&hp100_eisa_driver); if (err && err != -ENODEV) goto out2; +#endif +#ifdef CONFIG_PCI err = pci_register_driver(&hp100_pci_driver); if (err && err != -ENODEV) goto out3; +#endif out: return err; out3: +#ifdef CONFIG_EISA eisa_driver_unregister (&hp100_eisa_driver); out2: +#endif hp100_isa_cleanup(); goto out; } @@ -3043,8 +3057,12 @@ static int __init hp100_module_init(void) static void __exit hp100_module_exit(void) { hp100_isa_cleanup(); +#ifdef CONFIG_EISA eisa_driver_unregister (&hp100_eisa_driver); +#endif +#ifdef CONFIG_PCI pci_unregister_driver (&hp100_pci_driver); +#endif } module_init(hp100_module_init) diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index f301c03c527b..5d7db6c01c46 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -342,7 +342,6 @@ static int emac_reset(struct emac_instance *dev) { struct emac_regs __iomem *p = dev->emacp; int n = 20; - bool __maybe_unused try_internal_clock = false; DBG(dev, "reset" NL); @@ -355,7 +354,6 @@ static int emac_reset(struct emac_instance *dev) } #ifdef CONFIG_PPC_DCR_NATIVE -do_retry: /* * PPC460EX/GT Embedded Processor Advanced User's Manual * section 28.10.1 Mode Register 0 (EMACx_MR0) states: @@ -363,19 +361,10 @@ static int emac_reset(struct emac_instance *dev) * of the EMAC. If none is present, select the internal clock * (SDR0_ETH_CFG[EMACx_PHY_CLK] = 1). * After a soft reset, select the external clock. - * - * The AR8035-A PHY Meraki MR24 does not provide a TX Clk if the - * ethernet cable is not attached. This causes the reset to timeout - * and the PHY detection code in emac_init_phy() is unable to - * communicate and detect the AR8035-A PHY. As a result, the emac - * driver bails out early and the user has no ethernet. - * In order to stay compatible with existing configurations, the - * driver will temporarily switch to the internal clock, after - * the first reset fails. */ if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) { - if (try_internal_clock || (dev->phy_address == 0xffffffff && - dev->phy_map == 0xffffffff)) { + if (dev->phy_address == 0xffffffff && + dev->phy_map == 0xffffffff) { /* No PHY: select internal loop clock before reset */ dcri_clrset(SDR0, SDR0_ETH_CFG, 0, SDR0_ETH_CFG_ECS << dev->cell_index); @@ -393,15 +382,8 @@ static int emac_reset(struct emac_instance *dev) #ifdef CONFIG_PPC_DCR_NATIVE if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) { - if (!n && !try_internal_clock) { - /* first attempt has timed out. */ - n = 20; - try_internal_clock = true; - goto do_retry; - } - - if (try_internal_clock || (dev->phy_address == 0xffffffff && - dev->phy_map == 0xffffffff)) { + if (dev->phy_address == 0xffffffff && + dev->phy_map == 0xffffffff) { /* No PHY: restore external clock source after reset */ dcri_clrset(SDR0, SDR0_ETH_CFG, SDR0_ETH_CFG_ECS << dev->cell_index, 0); diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c index 81abe46c9e0d..fdb5cdb3cd15 100644 --- a/drivers/net/ethernet/ibm/emac/mal.c +++ b/drivers/net/ethernet/ibm/emac/mal.c @@ -402,7 +402,7 @@ static int mal_poll(struct napi_struct *napi, int budget) unsigned long flags; MAL_DBG2(mal, "poll(%d)" NL, budget); - + again: /* Process TX skbs */ list_for_each(l, &mal->poll_list) { struct mal_commac *mc = @@ -451,6 +451,7 @@ static int mal_poll(struct napi_struct *napi, int budget) spin_lock_irqsave(&mal->lock, flags); mal_disable_eob_irq(mal); spin_unlock_irqrestore(&mal->lock, flags); + goto again; } mc->ops->poll_tx(mc->dev); } diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 2f9b12cf9ee5..7af870a3c549 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -58,7 +58,7 @@ static struct kobj_type ktype_veth_pool; static const char ibmveth_driver_name[] = "ibmveth"; static const char ibmveth_driver_string[] = "IBM Power Virtual Ethernet Driver"; -#define ibmveth_driver_version "1.06" +#define ibmveth_driver_version "1.05" MODULE_AUTHOR("Santiago Leon "); MODULE_DESCRIPTION("IBM Power Virtual Ethernet Driver"); @@ -137,11 +137,6 @@ static inline int ibmveth_rxq_frame_offset(struct ibmveth_adapter *adapter) return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_OFF_MASK; } -static inline int ibmveth_rxq_large_packet(struct ibmveth_adapter *adapter) -{ - return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_LRG_PKT; -} - static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter) { return be32_to_cpu(adapter->rx_queue.queue_addr[adapter->rx_queue.index].length); @@ -1177,53 +1172,6 @@ static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb, goto retry_bounce; } -static void ibmveth_rx_mss_helper(struct sk_buff *skb, u16 mss, int lrg_pkt) -{ - struct tcphdr *tcph; - int offset = 0; - int hdr_len; - - /* only TCP packets will be aggregated */ - if (skb->protocol == htons(ETH_P_IP)) { - struct iphdr *iph = (struct iphdr *)skb->data; - - if (iph->protocol == IPPROTO_TCP) { - offset = iph->ihl * 4; - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; - } else { - return; - } - } else if (skb->protocol == htons(ETH_P_IPV6)) { - struct ipv6hdr *iph6 = (struct ipv6hdr *)skb->data; - - if (iph6->nexthdr == IPPROTO_TCP) { - offset = sizeof(struct ipv6hdr); - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; - } else { - return; - } - } else { - return; - } - /* if mss is not set through Large Packet bit/mss in rx buffer, - * expect that the mss will be written to the tcp header checksum. - */ - tcph = (struct tcphdr *)(skb->data + offset); - if (lrg_pkt) { - skb_shinfo(skb)->gso_size = mss; - } else if (offset) { - skb_shinfo(skb)->gso_size = ntohs(tcph->check); - tcph->check = 0; - } - - if (skb_shinfo(skb)->gso_size) { - hdr_len = offset + tcph->doff * 4; - skb_shinfo(skb)->gso_segs = - DIV_ROUND_UP(skb->len - hdr_len, - skb_shinfo(skb)->gso_size); - } -} - static int ibmveth_poll(struct napi_struct *napi, int budget) { struct ibmveth_adapter *adapter = @@ -1232,7 +1180,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget) int frames_processed = 0; unsigned long lpar_rc; struct iphdr *iph; - u16 mss = 0; restart_poll: while (frames_processed < budget) { @@ -1250,21 +1197,9 @@ static int ibmveth_poll(struct napi_struct *napi, int budget) int length = ibmveth_rxq_frame_length(adapter); int offset = ibmveth_rxq_frame_offset(adapter); int csum_good = ibmveth_rxq_csum_good(adapter); - int lrg_pkt = ibmveth_rxq_large_packet(adapter); skb = ibmveth_rxq_get_buffer(adapter); - /* if the large packet bit is set in the rx queue - * descriptor, the mss will be written by PHYP eight - * bytes from the start of the rx buffer, which is - * skb->data at this stage - */ - if (lrg_pkt) { - __be64 *rxmss = (__be64 *)(skb->data + 8); - - mss = (u16)be64_to_cpu(*rxmss); - } - new_skb = NULL; if (length < rx_copybreak) new_skb = netdev_alloc_skb(netdev, length); @@ -1298,15 +1233,11 @@ static int ibmveth_poll(struct napi_struct *napi, int budget) if (iph->check == 0xffff) { iph->check = 0; iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); + adapter->rx_large_packets++; } } } - if (length > netdev->mtu + ETH_HLEN) { - ibmveth_rx_mss_helper(skb, mss, lrg_pkt); - adapter->rx_large_packets++; - } - napi_gro_receive(napi, skb); /* send it up */ netdev->stats.rx_packets++; @@ -1602,11 +1533,8 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) netdev->netdev_ops = &ibmveth_netdev_ops; netdev->ethtool_ops = &netdev_ethtool_ops; SET_NETDEV_DEV(netdev, &dev->dev); - netdev->hw_features = NETIF_F_SG; - if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL) { - netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM; - } + netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; netdev->features |= netdev->hw_features; diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h index 7acda04d034e..4eade67fe30c 100644 --- a/drivers/net/ethernet/ibm/ibmveth.h +++ b/drivers/net/ethernet/ibm/ibmveth.h @@ -209,7 +209,6 @@ struct ibmveth_rx_q_entry { #define IBMVETH_RXQ_TOGGLE 0x80000000 #define IBMVETH_RXQ_TOGGLE_SHIFT 31 #define IBMVETH_RXQ_VALID 0x40000000 -#define IBMVETH_RXQ_LRG_PKT 0x04000000 #define IBMVETH_RXQ_NO_CSUM 0x02000000 #define IBMVETH_RXQ_CSUM_GOOD 0x01000000 #define IBMVETH_RXQ_OFF_MASK 0x0000FFFF diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h index 481e994490ce..69707108d23c 100644 --- a/drivers/net/ethernet/intel/e1000/e1000.h +++ b/drivers/net/ethernet/intel/e1000/e1000.h @@ -213,11 +213,8 @@ struct e1000_rx_ring { }; #define E1000_DESC_UNUSED(R) \ -({ \ - unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \ - unsigned int use = READ_ONCE((R)->next_to_use); \ - (clean > use ? 0 : (R)->count) + clean - use - 1; \ -}) + ((((R)->next_to_clean > (R)->next_to_use) \ + ? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1) #define E1000_RX_DESC_EXT(R, i) \ (&(((union e1000_rx_desc_extended *)((R).desc))[i])) @@ -331,8 +328,7 @@ struct e1000_adapter { enum e1000_state_t { __E1000_TESTING, __E1000_RESETTING, - __E1000_DOWN, - __E1000_DISABLED + __E1000_DOWN }; #undef pr_fmt diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 2a1d4a9d3c19..fd7be860c201 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -940,7 +940,7 @@ static int e1000_init_hw_struct(struct e1000_adapter *adapter, static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; - struct e1000_adapter *adapter = NULL; + struct e1000_adapter *adapter; struct e1000_hw *hw; static int cards_found = 0; @@ -950,7 +950,6 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) u16 tmp = 0; u16 eeprom_apme_mask = E1000_EEPROM_APME; int bars, need_ioport; - bool disable_dev = false; /* do not allocate ioport bars when not needed */ need_ioport = e1000_is_need_ioport(pdev); @@ -1251,13 +1250,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iounmap(hw->ce4100_gbe_mdio_base_virt); iounmap(hw->hw_addr); err_ioremap: - disable_dev = !test_and_set_bit(__E1000_DISABLED, &adapter->flags); free_netdev(netdev); err_alloc_etherdev: pci_release_selected_regions(pdev, bars); err_pci_reg: - if (!adapter || disable_dev) - pci_disable_device(pdev); + pci_disable_device(pdev); return err; } @@ -1275,7 +1272,6 @@ static void e1000_remove(struct pci_dev *pdev) struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - bool disable_dev; e1000_down_and_stop(adapter); e1000_release_manageability(adapter); @@ -1294,11 +1290,9 @@ static void e1000_remove(struct pci_dev *pdev) iounmap(hw->flash_address); pci_release_selected_regions(pdev, adapter->bars); - disable_dev = !test_and_set_bit(__E1000_DISABLED, &adapter->flags); free_netdev(netdev); - if (disable_dev) - pci_disable_device(pdev); + pci_disable_device(pdev); } /** @@ -3882,10 +3876,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, eop_desc = E1000_TX_DESC(*tx_ring, eop); } - /* Synchronize with E1000_DESC_UNUSED called from e1000_xmit_frame, - * which will reuse the cleaned buffers. - */ - smp_store_release(&tx_ring->next_to_clean, i); + tx_ring->next_to_clean = i; netdev_completed_queue(netdev, pkts_compl, bytes_compl); @@ -5141,8 +5132,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake) if (netif_running(netdev)) e1000_free_irq(adapter); - if (!test_and_set_bit(__E1000_DISABLED, &adapter->flags)) - pci_disable_device(pdev); + pci_disable_device(pdev); return 0; } @@ -5186,10 +5176,6 @@ static int e1000_resume(struct pci_dev *pdev) pr_err("Cannot enable PCI device from suspend\n"); return err; } - - /* flush memory to make sure state is correct */ - smp_mb__before_atomic(); - clear_bit(__E1000_DISABLED, &adapter->flags); pci_set_master(pdev); pci_enable_wake(pdev, PCI_D3hot, 0); @@ -5264,9 +5250,7 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, if (netif_running(netdev)) e1000_down(adapter); - - if (!test_and_set_bit(__E1000_DISABLED, &adapter->flags)) - pci_disable_device(pdev); + pci_disable_device(pdev); /* Request a slot slot reset. */ return PCI_ERS_RESULT_NEED_RESET; @@ -5294,10 +5278,6 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) pr_err("Cannot re-enable PCI device after reset.\n"); return PCI_ERS_RESULT_DISCONNECT; } - - /* flush memory to make sure state is correct */ - smp_mb__before_atomic(); - clear_bit(__E1000_DISABLED, &adapter->flags); pci_set_master(pdev); pci_enable_wake(pdev, PCI_D3hot, 0); diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index 485b9cc53f8b..91a5a0ae9cd7 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1362,9 +1362,6 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) * Checks to see of the link status of the hardware has changed. If a * change in link status has been detected, then we read the PHY registers * to get the current speed/duplex if link exists. - * - * Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link - * up). **/ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) { @@ -1380,7 +1377,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) * Change or Rx Sequence Error interrupt. */ if (!mac->get_link_status) - return 1; + return 0; /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex @@ -1574,7 +1571,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) * we have already determined whether we have link or not. */ if (!mac->autoneg) - return 1; + return -E1000_ERR_CONFIG; /* Auto-Neg is enabled. Auto Speed Detection takes care * of MAC speed/duplex configuration. So we only need to @@ -1588,12 +1585,10 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) * different link partner. */ ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { + if (ret_val) e_dbg("Error configuring flow control\n"); - return ret_val; - } - return 1; + return ret_val; } static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c index fe133f33a6c6..e59d7c283cd4 100644 --- a/drivers/net/ethernet/intel/e1000e/mac.c +++ b/drivers/net/ethernet/intel/e1000e/mac.c @@ -410,9 +410,6 @@ void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw) * Checks to see of the link status of the hardware has changed. If a * change in link status has been detected, then we read the PHY registers * to get the current speed/duplex if link exists. - * - * Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link - * up). **/ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) { @@ -426,7 +423,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) * Change or Rx Sequence Error interrupt. */ if (!mac->get_link_status) - return 1; + return 0; /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex @@ -450,7 +447,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) * we have already determined whether we have link or not. */ if (!mac->autoneg) - return 1; + return -E1000_ERR_CONFIG; /* Auto-Neg is enabled. Auto Speed Detection takes care * of MAC speed/duplex configuration. So we only need to @@ -464,12 +461,10 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) * different link partner. */ ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { + if (ret_val) e_dbg("Error configuring flow control\n"); - return ret_val; - } - return 1; + return ret_val; } /** diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 6369d88b81c1..0a854a47d31a 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -1182,7 +1182,6 @@ static void e1000e_tx_hwtstamp_work(struct work_struct *work) struct e1000_hw *hw = &adapter->hw; if (er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID) { - struct sk_buff *skb = adapter->tx_hwtstamp_skb; struct skb_shared_hwtstamps shhwtstamps; u64 txstmp; @@ -1191,14 +1190,9 @@ static void e1000e_tx_hwtstamp_work(struct work_struct *work) e1000e_systim_to_hwtstamp(adapter, &shhwtstamps, txstmp); - /* Clear the global tx_hwtstamp_skb pointer and force writes - * prior to notifying the stack of a Tx timestamp. - */ + skb_tstamp_tx(adapter->tx_hwtstamp_skb, &shhwtstamps); + dev_kfree_skb_any(adapter->tx_hwtstamp_skb); adapter->tx_hwtstamp_skb = NULL; - wmb(); /* force write prior to skb_tstamp_tx */ - - skb_tstamp_tx(skb, &shhwtstamps); - dev_kfree_skb_any(skb); } else if (time_after(jiffies, adapter->tx_hwtstamp_start + adapter->tx_timeout_factor * HZ)) { dev_kfree_skb_any(adapter->tx_hwtstamp_skb); @@ -1965,10 +1959,8 @@ static irqreturn_t e1000_intr_msix_rx(int __always_unused irq, void *data) * previous interrupt. */ if (rx_ring->set_itr) { - u32 itr = rx_ring->itr_val ? - 1000000000 / (rx_ring->itr_val * 256) : 0; - - writel(itr, rx_ring->itr_register); + writel(1000000000 / (rx_ring->itr_val * 256), + rx_ring->itr_register); rx_ring->set_itr = 0; } @@ -2330,8 +2322,8 @@ static int e1000_alloc_ring_dma(struct e1000_adapter *adapter, { struct pci_dev *pdev = adapter->pdev; - ring->desc = dma_zalloc_coherent(&pdev->dev, ring->size, &ring->dma, - GFP_KERNEL); + ring->desc = dma_alloc_coherent(&pdev->dev, ring->size, &ring->dma, + GFP_KERNEL); if (!ring->desc) return -ENOMEM; @@ -3532,12 +3524,6 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) switch (hw->mac.type) { case e1000_pch2lan: - /* Stable 96MHz frequency */ - incperiod = INCPERIOD_96MHz; - incvalue = INCVALUE_96MHz; - shift = INCVALUE_SHIFT_96MHz; - adapter->cc.shift = shift + INCPERIOD_SHIFT_96MHz; - break; case e1000_pch_lpt: if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) { /* Stable 96MHz frequency */ @@ -5029,7 +5015,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter) case e1000_media_type_copper: if (hw->mac.get_link_status) { ret_val = hw->mac.ops.check_for_link(hw); - link_active = ret_val > 0; + link_active = !hw->mac.get_link_status; } else { link_active = true; } @@ -5047,7 +5033,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter) break; } - if ((ret_val == -E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) && + if ((ret_val == E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) && (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) { /* See e1000_kmrn_lock_loss_workaround_ich8lan() */ e_info("Gigabit has been disabled, downgrading speed\n"); @@ -6595,17 +6581,12 @@ static int e1000e_pm_thaw(struct device *dev) static int e1000e_pm_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - int rc; e1000e_flush_lpic(pdev); e1000e_pm_freeze(dev); - rc = __e1000_shutdown(pdev, false); - if (rc) - e1000e_pm_thaw(dev); - - return rc; + return __e1000_shutdown(pdev, false); } static int e1000e_pm_resume(struct device *dev) diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c index 8e674a0988b0..de13aeacae97 100644 --- a/drivers/net/ethernet/intel/e1000e/phy.c +++ b/drivers/net/ethernet/intel/e1000e/phy.c @@ -1744,7 +1744,6 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, s32 ret_val = 0; u16 i, phy_status; - *success = false; for (i = 0; i < iterations; i++) { /* Some PHYs require the MII_BMSR register to be read * twice due to the link bit being sticky. No harm doing @@ -1764,16 +1763,16 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); if (ret_val) break; - if (phy_status & BMSR_LSTATUS) { - *success = true; + if (phy_status & BMSR_LSTATUS) break; - } if (usec_interval >= 1000) msleep(usec_interval / 1000); else udelay(usec_interval); } + *success = (i < iterations); + return ret_val; } diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h index 48809e5d3f79..14440200499b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k.h @@ -33,7 +33,7 @@ #include "fm10k_pf.h" #include "fm10k_vf.h" -#define FM10K_MAX_JUMBO_FRAME_SIZE 15342 /* Maximum supported size 15K */ +#define FM10K_MAX_JUMBO_FRAME_SIZE 15358 /* Maximum supported size 15K */ #define MAX_QUEUES FM10K_MAX_QUEUES_PF diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index 38431b49020f..2ce0eba5e040 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -983,7 +983,7 @@ static void fm10k_self_test(struct net_device *dev, memset(data, 0, sizeof(*data) * FM10K_TEST_LEN); - if (FM10K_REMOVED(hw->hw_addr)) { + if (FM10K_REMOVED(hw)) { netif_err(interface, drv, dev, "Interface removed - test blocked\n"); eth_test->flags |= ETH_TEST_FL_FAILED; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c index a8f9d0012d82..acfb8b1f88a7 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c @@ -126,9 +126,6 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface) struct fm10k_mbx_info *mbx = &vf_info->mbx; u16 glort = vf_info->glort; - /* process the SM mailbox first to drain outgoing messages */ - hw->mbx.ops.process(hw, &hw->mbx); - /* verify port mapping is valid, if not reset port */ if (vf_info->vf_flags && !fm10k_glort_valid_pf(hw, glort)) hw->iov.ops.reset_lport(hw, vf_info); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index c21fa56afd7c..e76a44cf330c 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1226,7 +1226,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector, break; /* prevent any other reads prior to eop_desc */ - smp_rmb(); + read_barrier_depends(); /* if DD is not set pending work has not been completed */ if (!(eop_desc->flags & FM10K_TXD_FLAG_DONE)) @@ -1428,10 +1428,6 @@ static int fm10k_poll(struct napi_struct *napi, int budget) fm10k_for_each_ring(ring, q_vector->tx) clean_complete &= fm10k_clean_tx_irq(q_vector, ring); - /* Handle case where we are called by netpoll with a budget of 0 */ - if (budget <= 0) - return budget; - /* attempt to distribute budget to each queue fairly, but don't * allow the budget to go below 1 because we'll exit polling */ @@ -1970,10 +1966,8 @@ int fm10k_init_queueing_scheme(struct fm10k_intfc *interface) /* Allocate memory for queues */ err = fm10k_alloc_q_vectors(interface); - if (err) { - fm10k_reset_msix_capability(interface); + if (err) return err; - } /* Map rings to devices, and map devices to physical queues */ fm10k_assign_rings(interface); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c index 6a2d1454befe..af09a1b272e6 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c @@ -2002,10 +2002,9 @@ static void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw, * function can also be used to respond to an error as the connection * resetting would also be a means of dealing with errors. **/ -static s32 fm10k_sm_mbx_process_reset(struct fm10k_hw *hw, - struct fm10k_mbx_info *mbx) +static void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw, + struct fm10k_mbx_info *mbx) { - s32 err = 0; const enum fm10k_mbx_state state = mbx->state; switch (state) { @@ -2018,7 +2017,6 @@ static s32 fm10k_sm_mbx_process_reset(struct fm10k_hw *hw, case FM10K_STATE_OPEN: /* flush any incomplete work */ fm10k_sm_mbx_connect_reset(mbx); - err = FM10K_ERR_RESET_REQUESTED; break; case FM10K_STATE_CONNECT: /* Update remote value to match local value */ @@ -2028,8 +2026,6 @@ static s32 fm10k_sm_mbx_process_reset(struct fm10k_hw *hw, } fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail); - - return err; } /** @@ -2110,7 +2106,7 @@ static s32 fm10k_sm_mbx_process(struct fm10k_hw *hw, switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) { case 0: - err = fm10k_sm_mbx_process_reset(hw, mbx); + fm10k_sm_mbx_process_reset(hw, mbx); break; case FM10K_SM_MBX_VERSION: err = fm10k_sm_mbx_process_version_1(hw, mbx); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 06f35700840b..74be792f3f1b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -159,30 +159,13 @@ static void fm10k_reinit(struct fm10k_intfc *interface) fm10k_mbx_free_irq(interface); - /* free interrupts */ - fm10k_clear_queueing_scheme(interface); - /* delay any future reset requests */ interface->last_reset = jiffies + (10 * HZ); /* reset and initialize the hardware so it is in a known state */ - err = hw->mac.ops.reset_hw(hw); - if (err) { - dev_err(&interface->pdev->dev, "reset_hw failed: %d\n", err); - goto reinit_err; - } - - err = hw->mac.ops.init_hw(hw); - if (err) { + err = hw->mac.ops.reset_hw(hw) ? : hw->mac.ops.init_hw(hw); + if (err) dev_err(&interface->pdev->dev, "init_hw failed: %d\n", err); - goto reinit_err; - } - - err = fm10k_init_queueing_scheme(interface); - if (err) { - dev_err(&interface->pdev->dev, "init_queueing_scheme failed: %d\n", err); - goto reinit_err; - } /* reassociate interrupts */ fm10k_mbx_request_irq(interface); @@ -210,10 +193,6 @@ static void fm10k_reinit(struct fm10k_intfc *interface) fm10k_iov_resume(interface->pdev); -reinit_err: - if (err) - netif_device_detach(netdev); - rtnl_unlock(); clear_bit(__FM10K_RESETTING, &interface->state); @@ -1072,7 +1051,6 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data) struct fm10k_hw *hw = &interface->hw; struct fm10k_mbx_info *mbx = &hw->mbx; u32 eicr; - s32 err = 0; /* unmask any set bits related to this interrupt */ eicr = fm10k_read_reg(hw, FM10K_EICR); @@ -1088,15 +1066,12 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data) /* service mailboxes */ if (fm10k_mbx_trylock(interface)) { - err = mbx->ops.process(hw, mbx); + mbx->ops.process(hw, mbx); /* handle VFLRE events */ fm10k_iov_event(interface); fm10k_mbx_unlock(interface); } - if (err == FM10K_ERR_RESET_REQUESTED) - interface->flags |= FM10K_FLAG_RESET_REQUESTED; - /* if switch toggled state we should reset GLORTs */ if (eicr & FM10K_EICR_SWITCHNOTREADY) { /* force link down for at least 4 seconds */ @@ -1126,10 +1101,6 @@ void fm10k_mbx_free_irq(struct fm10k_intfc *interface) struct fm10k_hw *hw = &interface->hw; int itr_reg; - /* no mailbox IRQ to free if MSI-X is not enabled */ - if (!interface->msix_entries) - return; - /* disconnect the mailbox */ hw->mbx.ops.disconnect(hw, &hw->mbx); @@ -1452,15 +1423,10 @@ int fm10k_mbx_request_irq(struct fm10k_intfc *interface) err = fm10k_mbx_request_irq_pf(interface); else err = fm10k_mbx_request_irq_vf(interface); - if (err) - return err; /* connect mailbox */ - err = hw->mbx.ops.connect(hw, &hw->mbx); - - /* if the mailbox failed to connect, then free IRQ */ - if (err) - fm10k_mbx_free_irq(interface); + if (!err) + err = hw->mbx.ops.connect(hw, &hw->mbx); return err; } @@ -1718,13 +1684,7 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, interface->last_reset = jiffies + (10 * HZ); /* reset and initialize the hardware so it is in a known state */ - err = hw->mac.ops.reset_hw(hw); - if (err) { - dev_err(&pdev->dev, "reset_hw failed: %d\n", err); - return err; - } - - err = hw->mac.ops.init_hw(hw); + err = hw->mac.ops.reset_hw(hw) ? : hw->mac.ops.init_hw(hw); if (err) { dev_err(&pdev->dev, "init_hw failed: %d\n", err); return err; @@ -2111,10 +2071,8 @@ static int fm10k_resume(struct pci_dev *pdev) /* reset hardware to known state */ err = hw->mac.ops.init_hw(&interface->hw); - if (err) { - dev_err(&pdev->dev, "init_hw failed: %d\n", err); + if (err) return err; - } /* reset statistics starting values */ hw->mac.ops.rebind_hw_stats(hw, &interface->stats); @@ -2227,9 +2185,6 @@ static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev, if (netif_running(netdev)) fm10k_close(netdev); - /* free interrupts */ - fm10k_clear_queueing_scheme(interface); - fm10k_mbx_free_irq(interface); pci_disable_device(pdev); @@ -2293,21 +2248,11 @@ static void fm10k_io_resume(struct pci_dev *pdev) int err = 0; /* reset hardware to known state */ - err = hw->mac.ops.init_hw(&interface->hw); - if (err) { - dev_err(&pdev->dev, "init_hw failed: %d\n", err); - return; - } + hw->mac.ops.init_hw(&interface->hw); /* reset statistics starting values */ hw->mac.ops.rebind_hw_stats(hw, &interface->stats); - err = fm10k_init_queueing_scheme(interface); - if (err) { - dev_err(&interface->pdev->dev, "init_queueing_scheme failed: %d\n", err); - return; - } - /* reassociate interrupts */ fm10k_mbx_request_irq(interface); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h index 35afd711d144..318a212f0a78 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h @@ -77,7 +77,6 @@ struct fm10k_hw; #define FM10K_PCIE_SRIOV_CTRL_VFARI 0x10 #define FM10K_ERR_PARAM -2 -#define FM10K_ERR_NO_RESOURCES -3 #define FM10K_ERR_REQUESTS_PENDING -4 #define FM10K_ERR_RESET_REQUESTED -5 #define FM10K_ERR_DMA_PENDING -6 diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c index d512575c33f3..36c8b0aa08fd 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c @@ -103,14 +103,7 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw) s32 err; u16 i; - /* verify we have at least 1 queue */ - if (!~fm10k_read_reg(hw, FM10K_TXQCTL(0)) || - !~fm10k_read_reg(hw, FM10K_RXQCTL(0))) { - err = FM10K_ERR_NO_RESOURCES; - goto reset_max_queues; - } - - /* determine how many queues we have */ + /* assume we always have at least 1 queue */ for (i = 1; tqdloc0 && (i < FM10K_MAX_QUEUES_POOL); i++) { /* verify the Descriptor cache offsets are increasing */ tqdloc = ~fm10k_read_reg(hw, FM10K_TQDLOC(i)); @@ -126,7 +119,7 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw) /* shut down queues we own and reset DMA configuration */ err = fm10k_disable_queues_generic(hw, i); if (err) - goto reset_max_queues; + return err; /* record maximum queue count */ hw->mac.max_queues = i; @@ -136,11 +129,6 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw) FM10K_TXQCTL_VID_MASK) >> FM10K_TXQCTL_VID_SHIFT; return 0; - -reset_max_queues: - hw->mac.max_queues = 0; - - return err; } /* This structure defines the attibutes to be parsed below */ diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 7e258a83ccab..4dd3e26129b4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -767,8 +767,6 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid); int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid); struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr, bool is_vf, bool is_netdev); -int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr, - bool is_vf, bool is_netdev); bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi); struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr, bool is_vf, bool is_netdev); diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 1cf715c72683..2d74c6e4d7b6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -302,15 +302,13 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc, void *buffer, u16 buf_len) { struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc; - u16 len; + u16 len = le16_to_cpu(aq_desc->datalen); u8 *buf = (u8 *)buffer; u16 i = 0; if ((!(mask & hw->debug_mask)) || (desc == NULL)) return; - len = le16_to_cpu(aq_desc->datalen); - i40e_debug(hw, mask, "AQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n", le16_to_cpu(aq_desc->opcode), diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 3da1f206ff84..3f385ffe420f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1073,11 +1073,6 @@ static int i40e_get_eeprom_len(struct net_device *netdev) struct i40e_hw *hw = &np->vsi->back->hw; u32 val; -#define X722_EEPROM_SCOPE_LIMIT 0x5B9FFF - if (hw->mac.type == I40E_MAC_X722) { - val = X722_EEPROM_SCOPE_LIMIT + 1; - return val; - } val = (rd32(hw, I40E_GLPCI_LBARCTRL) & I40E_GLPCI_LBARCTRL_FL_SIZE_MASK) >> I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT; @@ -2169,7 +2164,8 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case TCP_V4_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - return -EINVAL; + hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); + break; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); break; @@ -2180,7 +2176,8 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case TCP_V6_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - return -EINVAL; + hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); + break; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); break; @@ -2191,7 +2188,9 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case UDP_V4_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - return -EINVAL; + hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | + BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); + break; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); @@ -2203,7 +2202,9 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case UDP_V6_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - return -EINVAL; + hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | + BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); + break; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 06b38f50980c..4a9873ec28c7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1316,42 +1316,6 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr, struct i40e_mac_filter, list); } -/** - * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS - * @vsi: the VSI to be searched - * @macaddr: the mac address to be removed - * @is_vf: true if it is a VF - * @is_netdev: true if it is a netdev - * - * Removes a given MAC address from a VSI, regardless of VLAN - * - * Returns 0 for success, or error - **/ -int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr, - bool is_vf, bool is_netdev) -{ - struct i40e_mac_filter *f = NULL; - int changed = 0; - - WARN(!spin_is_locked(&vsi->mac_filter_list_lock), - "Missing mac_filter_list_lock\n"); - list_for_each_entry(f, &vsi->mac_filter_list, list) { - if ((ether_addr_equal(macaddr, f->macaddr)) && - (is_vf == f->is_vf) && - (is_netdev == f->is_netdev)) { - f->counter--; - f->changed = true; - changed = 1; - } - } - if (changed) { - vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; - vsi->back->flags |= I40E_FLAG_FILTER_SYNC; - return 0; - } - return -ENOENT; -} - /** * i40e_rm_default_mac_filter - Remove the default MAC filter set by NVM * @vsi: the PF Main VSI - inappropriate for any other VSI @@ -1583,11 +1547,9 @@ static int i40e_set_mac(struct net_device *netdev, void *p) spin_unlock_bh(&vsi->mac_filter_list_lock); } + i40e_sync_vsi_filters(vsi, false); ether_addr_copy(netdev->dev_addr, addr->sa_data); - /* schedule our worker thread which will take care of - * applying the new filter changes - */ - i40e_service_event_schedule(vsi->back); + return 0; } @@ -1973,13 +1935,11 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) /* Now process 'del_list' outside the lock */ if (!list_empty(&tmp_del_list)) { - int del_list_size; - filter_list_len = pf->hw.aq.asq_buf_size / sizeof(struct i40e_aqc_remove_macvlan_element_data); - del_list_size = filter_list_len * - sizeof(struct i40e_aqc_remove_macvlan_element_data); - del_list = kzalloc(del_list_size, GFP_KERNEL); + del_list = kcalloc(filter_list_len, + sizeof(struct i40e_aqc_remove_macvlan_element_data), + GFP_KERNEL); if (!del_list) { i40e_cleanup_add_list(&tmp_add_list); @@ -2011,7 +1971,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) NULL); aq_err = pf->hw.aq.asq_last_status; num_del = 0; - memset(del_list, 0, del_list_size); + memset(del_list, 0, sizeof(*del_list)); if (ret && aq_err != I40E_AQ_RC_ENOENT) dev_err(&pf->pdev->dev, @@ -2044,14 +2004,13 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) } if (!list_empty(&tmp_add_list)) { - int add_list_size; /* do all the adds now */ filter_list_len = pf->hw.aq.asq_buf_size / sizeof(struct i40e_aqc_add_macvlan_element_data), - add_list_size = filter_list_len * - sizeof(struct i40e_aqc_add_macvlan_element_data); - add_list = kzalloc(add_list_size, GFP_KERNEL); + add_list = kcalloc(filter_list_len, + sizeof(struct i40e_aqc_add_macvlan_element_data), + GFP_KERNEL); if (!add_list) { /* Purge element from temporary lists */ i40e_cleanup_add_list(&tmp_add_list); @@ -2089,7 +2048,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) if (ret) break; - memset(add_list, 0, add_list_size); + memset(add_list, 0, sizeof(*add_list)); } /* Entries from tmp_add_list were cloned from MAC * filter list, hence clean those cloned entries @@ -2153,7 +2112,12 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) */ if (pf->cur_promisc != cur_promisc) { pf->cur_promisc = cur_promisc; - set_bit(__I40E_PF_RESET_REQUESTED, &pf->state); + if (grab_rtnl) + i40e_do_reset_safe(pf, + BIT(__I40E_PF_RESET_REQUESTED)); + else + i40e_do_reset(pf, + BIT(__I40E_PF_RESET_REQUESTED)); } } else { ret = i40e_aq_set_vsi_unicast_promiscuous( @@ -2413,13 +2377,16 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) } } + /* Make sure to release before sync_vsi_filter because that + * function will lock/unlock as necessary + */ spin_unlock_bh(&vsi->mac_filter_list_lock); - /* schedule our worker thread which will take care of - * applying the new filter changes - */ - i40e_service_event_schedule(vsi->back); - return 0; + if (test_bit(__I40E_DOWN, &vsi->back->state) || + test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) + return 0; + + return i40e_sync_vsi_filters(vsi, false); } /** @@ -2492,13 +2459,16 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) } } + /* Make sure to release before sync_vsi_filter because that + * function with lock/unlock as necessary + */ spin_unlock_bh(&vsi->mac_filter_list_lock); - /* schedule our worker thread which will take care of - * applying the new filter changes - */ - i40e_service_event_schedule(vsi->back); - return 0; + if (test_bit(__I40E_DOWN, &vsi->back->state) || + test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) + return 0; + + return i40e_sync_vsi_filters(vsi, false); } /** @@ -2741,11 +2711,6 @@ static void i40e_config_xps_tx_ring(struct i40e_ring *ring) netif_set_xps_queue(ring->netdev, mask, ring->queue_index); free_cpumask_var(mask); } - - /* schedule our worker thread which will take care of - * applying the new filter changes - */ - i40e_service_event_schedule(vsi->back); } /** @@ -3595,7 +3560,7 @@ static bool i40e_clean_fdir_tx_irq(struct i40e_ring *tx_ring, int budget) break; /* prevent any other reads prior to eop_desc */ - smp_rmb(); + read_barrier_depends(); /* if the descriptor isn't done, no work yet to do */ if (!(eop_desc->cmd_type_offset_bsz & @@ -4201,12 +4166,8 @@ static void i40e_napi_enable_all(struct i40e_vsi *vsi) if (!vsi->netdev) return; - for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) { - struct i40e_q_vector *q_vector = vsi->q_vectors[q_idx]; - - if (q_vector->rx.ring || q_vector->tx.ring) - napi_enable(&q_vector->napi); - } + for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) + napi_enable(&vsi->q_vectors[q_idx]->napi); } /** @@ -4220,12 +4181,8 @@ static void i40e_napi_disable_all(struct i40e_vsi *vsi) if (!vsi->netdev) return; - for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) { - struct i40e_q_vector *q_vector = vsi->q_vectors[q_idx]; - - if (q_vector->rx.ring || q_vector->tx.ring) - napi_disable(&q_vector->napi); - } + for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) + napi_disable(&vsi->q_vectors[q_idx]->napi); } /** @@ -6728,7 +6685,6 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) struct i40e_hw *hw = &pf->hw; u8 set_fc_aq_fail = 0; i40e_status ret; - u32 val; u32 v; /* Now we wait for GRST to settle out. @@ -6867,20 +6823,6 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) } } - /* Reconfigure hardware for allowing smaller MSS in the case - * of TSO, so that we avoid the MDD being fired and causing - * a reset in the case of small MSS+TSO. - */ -#define I40E_REG_MSS 0x000E64DC -#define I40E_REG_MSS_MIN_MASK 0x3FF0000 -#define I40E_64BYTE_MSS 0x400000 - val = rd32(hw, I40E_REG_MSS); - if ((val & I40E_REG_MSS_MIN_MASK) > I40E_64BYTE_MSS) { - val &= ~I40E_REG_MSS_MIN_MASK; - val |= I40E_64BYTE_MSS; - wr32(hw, I40E_REG_MSS, val); - } - if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) || (pf->hw.aq.fw_maj_ver < 4)) { msleep(75); @@ -8603,7 +8545,7 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, return 0; return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode, - 0, 0, nlflags, filter_mask, NULL); + nlflags, 0, 0, filter_mask, NULL); } #define I40E_MAX_TUNNEL_HDR_LEN 80 @@ -10241,7 +10183,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) u16 link_status; int err; u32 len; - u32 val; u32 i; u8 set_fc_aq_fail; @@ -10552,17 +10493,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i40e_stat_str(&pf->hw, err), i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); - /* Reconfigure hardware for allowing smaller MSS in the case - * of TSO, so that we avoid the MDD being fired and causing - * a reset in the case of small MSS+TSO. - */ - val = rd32(hw, I40E_REG_MSS); - if ((val & I40E_REG_MSS_MIN_MASK) > I40E_64BYTE_MSS) { - val &= ~I40E_REG_MSS_MIN_MASK; - val |= I40E_64BYTE_MSS; - wr32(hw, I40E_REG_MSS, val); - } - if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) || (pf->hw.aq.fw_maj_ver < 4)) { msleep(75); @@ -10861,12 +10791,6 @@ static pci_ers_result_t i40e_pci_error_detected(struct pci_dev *pdev, dev_info(&pdev->dev, "%s: error %d\n", __func__, error); - if (!pf) { - dev_info(&pdev->dev, - "Cannot recover - error happened during device probe\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - /* shutdown all operations */ if (!test_bit(__I40E_SUSPENDED, &pf->state)) { rtnl_lock(); diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index dd4e6ea9e0e1..6100cdd9ad13 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -292,14 +292,14 @@ i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, { enum i40e_status_code ret_code = 0; - ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); - if (!ret_code) { - if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) { + if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) { + ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); + if (!ret_code) { ret_code = i40e_read_nvm_word_aq(hw, offset, data); - } else { - ret_code = i40e_read_nvm_word_srctl(hw, offset, data); + i40e_release_nvm(hw); } - i40e_release_nvm(hw); + } else { + ret_code = i40e_read_nvm_word_srctl(hw, offset, data); } return ret_code; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 6dcc3854844d..635b3ac17877 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -235,9 +235,6 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi, "Filter deleted for PCTYPE %d loc = %d\n", fd_data->pctype, fd_data->fd_id); } - if (err) - kfree(raw_packet); - return err ? -EOPNOTSUPP : 0; } @@ -315,9 +312,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi, fd_data->pctype, fd_data->fd_id); } - if (err) - kfree(raw_packet); - return err ? -EOPNOTSUPP : 0; } @@ -393,9 +387,6 @@ static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi, } } - if (err) - kfree(raw_packet); - return err ? -EOPNOTSUPP : 0; } @@ -535,7 +526,11 @@ static void i40e_unmap_and_free_tx_resource(struct i40e_ring *ring, struct i40e_tx_buffer *tx_buffer) { if (tx_buffer->skb) { - dev_kfree_skb_any(tx_buffer->skb); + if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB) + kfree(tx_buffer->raw_buf); + else + dev_kfree_skb_any(tx_buffer->skb); + if (dma_unmap_len(tx_buffer, len)) dma_unmap_single(ring->dev, dma_unmap_addr(tx_buffer, dma), @@ -547,10 +542,6 @@ static void i40e_unmap_and_free_tx_resource(struct i40e_ring *ring, dma_unmap_len(tx_buffer, len), DMA_TO_DEVICE); } - - if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB) - kfree(tx_buffer->raw_buf); - tx_buffer->next_to_watch = NULL; tx_buffer->skb = NULL; dma_unmap_len_set(tx_buffer, len, 0); @@ -663,7 +654,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) break; /* prevent any other reads prior to eop_desc */ - smp_rmb(); + read_barrier_depends(); /* we have caught up to head, no work left to do */ if (tx_head == tx_desc) @@ -1425,12 +1416,31 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, } /** - * i40e_ptype_to_htype - get a hash type + * i40e_rx_hash - returns the hash value from the Rx descriptor + * @ring: descriptor ring + * @rx_desc: specific descriptor + **/ +static inline u32 i40e_rx_hash(struct i40e_ring *ring, + union i40e_rx_desc *rx_desc) +{ + const __le64 rss_mask = + cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH << + I40E_RX_DESC_STATUS_FLTSTAT_SHIFT); + + if ((ring->netdev->features & NETIF_F_RXHASH) && + (rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) + return le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss); + else + return 0; +} + +/** + * i40e_ptype_to_hash - get a hash type * @ptype: the ptype value from the descriptor * * Returns a hash type to be used by skb_set_hash **/ -static inline enum pkt_hash_types i40e_ptype_to_htype(u8 ptype) +static inline enum pkt_hash_types i40e_ptype_to_hash(u8 ptype) { struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype); @@ -1447,30 +1457,6 @@ static inline enum pkt_hash_types i40e_ptype_to_htype(u8 ptype) return PKT_HASH_TYPE_L2; } -/** - * i40e_rx_hash - set the hash value in the skb - * @ring: descriptor ring - * @rx_desc: specific descriptor - **/ -static inline void i40e_rx_hash(struct i40e_ring *ring, - union i40e_rx_desc *rx_desc, - struct sk_buff *skb, - u8 rx_ptype) -{ - u32 hash; - const __le64 rss_mask = - cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH << - I40E_RX_DESC_STATUS_FLTSTAT_SHIFT); - - if (ring->netdev->features & NETIF_F_RXHASH) - return; - - if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) { - hash = le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss); - skb_set_hash(skb, hash, i40e_ptype_to_htype(rx_ptype)); - } -} - /** * i40e_clean_rx_irq_ps - Reclaim resources after receive; packet split * @rx_ring: rx ring to clean @@ -1620,8 +1606,8 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget) continue; } - i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype); - + skb_set_hash(skb, i40e_rx_hash(rx_ring, rx_desc), + i40e_ptype_to_hash(rx_ptype)); if (unlikely(rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK)) { i40e_ptp_rx_hwtstamp(vsi->back, skb, (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >> @@ -1750,7 +1736,8 @@ static int i40e_clean_rx_irq_1buf(struct i40e_ring *rx_ring, int budget) continue; } - i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype); + skb_set_hash(skb, i40e_rx_hash(rx_ring, rx_desc), + i40e_ptype_to_hash(rx_ptype)); if (unlikely(rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK)) { i40e_ptp_rx_hwtstamp(vsi->back, skb, (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >> diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index e116d9a99b8e..44462b40f2d7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -549,15 +549,12 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) i40e_vsi_add_pvid(vsi, vf->port_vlan_id); spin_lock_bh(&vsi->mac_filter_list_lock); - if (is_valid_ether_addr(vf->default_lan_addr.addr)) { - f = i40e_add_filter(vsi, vf->default_lan_addr.addr, - vf->port_vlan_id ? vf->port_vlan_id : -1, - true, false); - if (!f) - dev_info(&pf->pdev->dev, - "Could not add MAC filter %pM for VF %d\n", - vf->default_lan_addr.addr, vf->vf_id); - } + f = i40e_add_filter(vsi, vf->default_lan_addr.addr, + vf->port_vlan_id ? vf->port_vlan_id : -1, + true, false); + if (!f) + dev_info(&pf->pdev->dev, + "Could not allocate VF MAC addr\n"); f = i40e_add_filter(vsi, brdcast, vf->port_vlan_id ? vf->port_vlan_id : -1, true, false); @@ -1683,12 +1680,8 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) spin_lock_bh(&vsi->mac_filter_list_lock); /* delete addresses from the list */ for (i = 0; i < al->num_elements; i++) - if (i40e_del_mac_all_vlan(vsi, al->list[i].addr, true, false)) { - ret = I40E_ERR_INVALID_MAC_ADDR; - spin_unlock_bh(&vsi->mac_filter_list_lock); - goto error_param; - } - + i40e_del_filter(vsi, al->list[i].addr, + I40E_VLAN_ANY, true, false); spin_unlock_bh(&vsi->mac_filter_list_lock); /* program the updated filter list */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 1ed27fcd5031..47e9a90d6b10 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -51,7 +51,11 @@ static void i40e_unmap_and_free_tx_resource(struct i40e_ring *ring, struct i40e_tx_buffer *tx_buffer) { if (tx_buffer->skb) { - dev_kfree_skb_any(tx_buffer->skb); + if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB) + kfree(tx_buffer->raw_buf); + else + dev_kfree_skb_any(tx_buffer->skb); + if (dma_unmap_len(tx_buffer, len)) dma_unmap_single(ring->dev, dma_unmap_addr(tx_buffer, dma), @@ -63,10 +67,6 @@ static void i40e_unmap_and_free_tx_resource(struct i40e_ring *ring, dma_unmap_len(tx_buffer, len), DMA_TO_DEVICE); } - - if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB) - kfree(tx_buffer->raw_buf); - tx_buffer->next_to_watch = NULL; tx_buffer->skb = NULL; dma_unmap_len_set(tx_buffer, len, 0); @@ -172,7 +172,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) break; /* prevent any other reads prior to eop_desc */ - smp_rmb(); + read_barrier_depends(); /* we have caught up to head, no work left to do */ if (tx_head == tx_desc) @@ -245,6 +245,16 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) tx_ring->q_vector->tx.total_bytes += total_bytes; tx_ring->q_vector->tx.total_packets += total_packets; + /* check to see if there are any non-cache aligned descriptors + * waiting to be written back, and kick the hardware to force + * them to be written back in case of napi polling + */ + if (budget && + !((i & WB_STRIDE) == WB_STRIDE) && + !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && + (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) + tx_ring->arm_wb = true; + netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index), total_packets, total_bytes); @@ -879,12 +889,31 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, } /** - * i40e_ptype_to_htype - get a hash type + * i40e_rx_hash - returns the hash value from the Rx descriptor + * @ring: descriptor ring + * @rx_desc: specific descriptor + **/ +static inline u32 i40e_rx_hash(struct i40e_ring *ring, + union i40e_rx_desc *rx_desc) +{ + const __le64 rss_mask = + cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH << + I40E_RX_DESC_STATUS_FLTSTAT_SHIFT); + + if ((ring->netdev->features & NETIF_F_RXHASH) && + (rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) + return le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss); + else + return 0; +} + +/** + * i40e_ptype_to_hash - get a hash type * @ptype: the ptype value from the descriptor * * Returns a hash type to be used by skb_set_hash **/ -static inline enum pkt_hash_types i40e_ptype_to_htype(u8 ptype) +static inline enum pkt_hash_types i40e_ptype_to_hash(u8 ptype) { struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype); @@ -901,30 +930,6 @@ static inline enum pkt_hash_types i40e_ptype_to_htype(u8 ptype) return PKT_HASH_TYPE_L2; } -/** - * i40e_rx_hash - set the hash value in the skb - * @ring: descriptor ring - * @rx_desc: specific descriptor - **/ -static inline void i40e_rx_hash(struct i40e_ring *ring, - union i40e_rx_desc *rx_desc, - struct sk_buff *skb, - u8 rx_ptype) -{ - u32 hash; - const __le64 rss_mask = - cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH << - I40E_RX_DESC_STATUS_FLTSTAT_SHIFT); - - if (ring->netdev->features & NETIF_F_RXHASH) - return; - - if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) { - hash = le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss); - skb_set_hash(skb, hash, i40e_ptype_to_htype(rx_ptype)); - } -} - /** * i40e_clean_rx_irq_ps - Reclaim resources after receive; packet split * @rx_ring: rx ring to clean @@ -1066,8 +1071,8 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget) continue; } - i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype); - + skb_set_hash(skb, i40e_rx_hash(rx_ring, rx_desc), + i40e_ptype_to_hash(rx_ptype)); /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; total_rx_packets++; @@ -1184,7 +1189,8 @@ static int i40e_clean_rx_irq_1buf(struct i40e_ring *rx_ring, int budget) continue; } - i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype); + skb_set_hash(skb, i40e_rx_hash(rx_ring, rx_desc), + i40e_ptype_to_hash(rx_ptype)); /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; total_rx_packets++; @@ -1764,9 +1770,6 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, u32 td_tag = 0; dma_addr_t dma; u16 gso_segs; - u16 desc_count = 0; - bool tail_bump = true; - bool do_rs = false; if (tx_flags & I40E_TX_FLAGS_HW_VLAN) { td_cmd |= I40E_TX_DESC_CMD_IL2TAG1; @@ -1807,8 +1810,6 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_desc++; i++; - desc_count++; - if (i == tx_ring->count) { tx_desc = I40E_TX_DESC(tx_ring, 0); i = 0; @@ -1828,8 +1829,6 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_desc++; i++; - desc_count++; - if (i == tx_ring->count) { tx_desc = I40E_TX_DESC(tx_ring, 0); i = 0; @@ -1844,7 +1843,35 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_bi = &tx_ring->tx_bi[i]; } + /* Place RS bit on last descriptor of any packet that spans across the + * 4th descriptor (WB_STRIDE aka 0x3) in a 64B cacheline. + */ #define WB_STRIDE 0x3 + if (((i & WB_STRIDE) != WB_STRIDE) && + (first <= &tx_ring->tx_bi[i]) && + (first >= &tx_ring->tx_bi[i & ~WB_STRIDE])) { + tx_desc->cmd_type_offset_bsz = + build_ctob(td_cmd, td_offset, size, td_tag) | + cpu_to_le64((u64)I40E_TX_DESC_CMD_EOP << + I40E_TXD_QW1_CMD_SHIFT); + } else { + tx_desc->cmd_type_offset_bsz = + build_ctob(td_cmd, td_offset, size, td_tag) | + cpu_to_le64((u64)I40E_TXD_CMD << + I40E_TXD_QW1_CMD_SHIFT); + } + + netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev, + tx_ring->queue_index), + first->bytecount); + + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + /* set next_to_watch value indicating a packet is present */ first->next_to_watch = tx_desc; @@ -1854,77 +1881,14 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_ring->next_to_use = i; - netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev, - tx_ring->queue_index), - first->bytecount); i40evf_maybe_stop_tx(tx_ring, DESC_NEEDED); - - /* Algorithm to optimize tail and RS bit setting: - * if xmit_more is supported - * if xmit_more is true - * do not update tail and do not mark RS bit. - * if xmit_more is false and last xmit_more was false - * if every packet spanned less than 4 desc - * then set RS bit on 4th packet and update tail - * on every packet - * else - * update tail and set RS bit on every packet. - * if xmit_more is false and last_xmit_more was true - * update tail and set RS bit. - * else (kernel < 3.18) - * if every packet spanned less than 4 desc - * then set RS bit on 4th packet and update tail - * on every packet - * else - * set RS bit on EOP for every packet and update tail - * - * Optimization: wmb to be issued only in case of tail update. - * Also optimize the Descriptor WB path for RS bit with the same - * algorithm. - * - * Note: If there are less than 4 packets - * pending and interrupts were disabled the service task will - * trigger a force WB. - */ - if (skb->xmit_more && - !netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev, - tx_ring->queue_index))) { - tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; - tail_bump = false; - } else if (!skb->xmit_more && - !netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev, - tx_ring->queue_index)) && - (!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) && - (tx_ring->packet_stride < WB_STRIDE) && - (desc_count < WB_STRIDE)) { - tx_ring->packet_stride++; - } else { - tx_ring->packet_stride = 0; - tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; - do_rs = true; - } - if (do_rs) - tx_ring->packet_stride = 0; - - tx_desc->cmd_type_offset_bsz = - build_ctob(td_cmd, td_offset, size, td_tag) | - cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD : - I40E_TX_DESC_CMD_EOP) << - I40E_TXD_QW1_CMD_SHIFT); - /* notify HW of packet */ - if (!tail_bump) - prefetchw(tx_desc + 1); - - if (tail_bump) { - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); + if (!skb->xmit_more || + netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev, + tx_ring->queue_index))) writel(i, tx_ring->tail); - } + else + prefetchw(tx_desc + 1); return; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index 998976844e4e..ebc1bf77f036 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -267,8 +267,6 @@ struct i40e_ring { bool ring_active; /* is ring online or not */ bool arm_wb; /* do something to arm write back */ - u8 packet_stride; -#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2) u16 flags; #define I40E_TXR_FLAGS_WB_ON_ITR BIT(0) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c index 2ac62efc36f7..4790437a50ac 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c @@ -477,30 +477,54 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, switch (nfc->flow_type) { case TCP_V4_FLOW: - if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); - else + break; + default: return -EINVAL; + } break; case TCP_V6_FLOW: - if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); - else + break; + default: return -EINVAL; + } break; case UDP_V4_FLOW: - if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | + BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); - } else { + break; + default: return -EINVAL; } break; case UDP_V6_FLOW: - if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | + BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); - } else { + break; + default: return -EINVAL; } break; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 5f03ab3dfa19..99d2cffae0cd 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1864,9 +1864,6 @@ void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter) { int i; - if (!adapter->tx_rings) - return; - for (i = 0; i < adapter->num_active_queues; i++) if (adapter->tx_rings[i]->desc) i40evf_free_tx_resources(adapter->tx_rings[i]); @@ -1935,9 +1932,6 @@ void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter) { int i; - if (!adapter->rx_rings) - return; - for (i = 0; i < adapter->num_active_queues; i++) if (adapter->rx_rings[i]->desc) i40evf_free_rx_resources(adapter->rx_rings[i]); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index 5de3f52fd31f..32e620e1eb5c 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -391,7 +391,6 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter) struct i40e_virtchnl_ether_addr_list *veal; int len, i = 0, count = 0; struct i40evf_mac_filter *f; - bool more = false; if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ @@ -416,9 +415,7 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter) count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_ether_addr_list)) / sizeof(struct i40e_virtchnl_ether_addr); - len = sizeof(struct i40e_virtchnl_ether_addr_list) + - (count * sizeof(struct i40e_virtchnl_ether_addr)); - more = true; + len = I40EVF_MAX_AQ_BUF_SIZE; } veal = kzalloc(len, GFP_ATOMIC); @@ -434,8 +431,7 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter) f->add = false; } } - if (!more) - adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER; + adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER; i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS, (u8 *)veal, len); kfree(veal); @@ -454,7 +450,6 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter) struct i40e_virtchnl_ether_addr_list *veal; struct i40evf_mac_filter *f, *ftmp; int len, i = 0, count = 0; - bool more = false; if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ @@ -479,9 +474,7 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter) count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_ether_addr_list)) / sizeof(struct i40e_virtchnl_ether_addr); - len = sizeof(struct i40e_virtchnl_ether_addr_list) + - (count * sizeof(struct i40e_virtchnl_ether_addr)); - more = true; + len = I40EVF_MAX_AQ_BUF_SIZE; } veal = kzalloc(len, GFP_ATOMIC); if (!veal) @@ -497,8 +490,7 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter) kfree(f); } } - if (!more) - adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER; + adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER; i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS, (u8 *)veal, len); kfree(veal); @@ -517,7 +509,6 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter) struct i40e_virtchnl_vlan_filter_list *vvfl; int len, i = 0, count = 0; struct i40evf_vlan_filter *f; - bool more = false; if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ @@ -543,9 +534,7 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter) count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_vlan_filter_list)) / sizeof(u16); - len = sizeof(struct i40e_virtchnl_vlan_filter_list) + - (count * sizeof(u16)); - more = true; + len = I40EVF_MAX_AQ_BUF_SIZE; } vvfl = kzalloc(len, GFP_ATOMIC); if (!vvfl) @@ -560,8 +549,7 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter) f->add = false; } } - if (!more) - adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER; + adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER; i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len); kfree(vvfl); } @@ -579,7 +567,6 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter) struct i40e_virtchnl_vlan_filter_list *vvfl; struct i40evf_vlan_filter *f, *ftmp; int len, i = 0, count = 0; - bool more = false; if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ @@ -605,9 +592,7 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter) count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_vlan_filter_list)) / sizeof(u16); - len = sizeof(struct i40e_virtchnl_vlan_filter_list) + - (count * sizeof(u16)); - more = true; + len = I40EVF_MAX_AQ_BUF_SIZE; } vvfl = kzalloc(len, GFP_ATOMIC); if (!vvfl) @@ -623,8 +608,7 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter) kfree(f); } } - if (!more) - adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER; + adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER; i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_VLAN, (u8 *)vvfl, len); kfree(vvfl); } diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index f3f3b95d5512..7a73510e547c 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -223,17 +223,6 @@ static s32 igb_init_phy_params_82575(struct e1000_hw *hw) hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; - /* Make sure the PHY is in a good state. Several people have reported - * firmware leaving the PHY's page select register set to something - * other than the default of zero, which causes the PHY ID read to - * access something other than the intended register. - */ - ret_val = hw->phy.ops.reset(hw); - if (ret_val) { - hw_dbg("Error resetting the PHY.\n"); - goto out; - } - /* Set phy->phy_addr and phy->id. */ ret_val = igb_get_phy_id_82575(hw); if (ret_val) @@ -305,7 +294,6 @@ static s32 igb_init_phy_params_82575(struct e1000_hw *hw) case I210_I_PHY_ID: phy->type = e1000_phy_i210; phy->ops.check_polarity = igb_check_polarity_m88; - phy->ops.get_cfg_done = igb_get_cfg_done_i210; phy->ops.get_phy_info = igb_get_phy_info_m88; phy->ops.get_cable_length = igb_get_cable_length_m88_gen2; phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580; diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c index 851225b5dc0f..65d931669f81 100644 --- a/drivers/net/ethernet/intel/igb/e1000_i210.c +++ b/drivers/net/ethernet/intel/igb/e1000_i210.c @@ -699,9 +699,9 @@ static s32 igb_update_flash_i210(struct e1000_hw *hw) ret_val = igb_pool_flash_update_done_i210(hw); if (ret_val) - hw_dbg("Flash update time out\n"); - else hw_dbg("Flash update complete\n"); + else + hw_dbg("Flash update time out\n"); out: return ret_val; @@ -900,30 +900,3 @@ s32 igb_pll_workaround_i210(struct e1000_hw *hw) wr32(E1000_MDICNFG, mdicnfg); return ret_val; } - -/** - * igb_get_cfg_done_i210 - Read config done bit - * @hw: pointer to the HW structure - * - * Read the management control register for the config done bit for - * completion status. NOTE: silicon which is EEPROM-less will fail trying - * to read the config done bit, so an error is *ONLY* logged and returns - * 0. If we were to return with error, EEPROM-less silicon - * would not be able to be reset or change link. - **/ -s32 igb_get_cfg_done_i210(struct e1000_hw *hw) -{ - s32 timeout = PHY_CFG_TIMEOUT; - u32 mask = E1000_NVM_CFG_DONE_PORT_0; - - while (timeout) { - if (rd32(E1000_EEMNGCTL_I210) & mask) - break; - usleep_range(1000, 2000); - timeout--; - } - if (!timeout) - hw_dbg("MNG configuration cycle has not completed.\n"); - - return 0; -} diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.h b/drivers/net/ethernet/intel/igb/e1000_i210.h index eaa68a50cb3b..3442b6357d01 100644 --- a/drivers/net/ethernet/intel/igb/e1000_i210.h +++ b/drivers/net/ethernet/intel/igb/e1000_i210.h @@ -34,7 +34,6 @@ s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data); s32 igb_init_nvm_params_i210(struct e1000_hw *hw); bool igb_get_flash_presence_i210(struct e1000_hw *hw); s32 igb_pll_workaround_i210(struct e1000_hw *hw); -s32 igb_get_cfg_done_i210(struct e1000_hw *hw); #define E1000_STM_OPCODE 0xDB00 #define E1000_EEPROM_FLASH_SIZE_WORD 0x11 diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c index afaa98d1d4e4..23ec28f43f6d 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.c +++ b/drivers/net/ethernet/intel/igb/e1000_phy.c @@ -77,10 +77,6 @@ s32 igb_get_phy_id(struct e1000_hw *hw) s32 ret_val = 0; u16 phy_id; - /* ensure PHY page selection to fix misconfigured i210 */ - if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) - phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0); - ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); if (ret_val) goto out; diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h index 0fdcd4d1b982..4af2870e49f8 100644 --- a/drivers/net/ethernet/intel/igb/e1000_regs.h +++ b/drivers/net/ethernet/intel/igb/e1000_regs.h @@ -66,7 +66,6 @@ #define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ #define E1000_PBS 0x01008 /* Packet Buffer Size */ #define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ -#define E1000_EEMNGCTL_I210 0x12030 /* MNG EEprom Control */ #define E1000_EEARBC_I210 0x12024 /* EEPROM Auto Read Bus Control */ #define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ #define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */ diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index e3cb93bdb21a..1a2f1cc44b28 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -389,8 +389,6 @@ struct igb_adapter { u16 link_speed; u16 link_duplex; - u8 __iomem *io_addr; /* Mainly for iounmap use */ - struct work_struct reset_task; struct work_struct watchdog_task; bool fc_autoneg; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 02b23f6277fb..ea7b09887245 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2294,11 +2294,9 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); err = -EIO; - adapter->io_addr = pci_iomap(pdev, 0, 0); - if (!adapter->io_addr) + hw->hw_addr = pci_iomap(pdev, 0, 0); + if (!hw->hw_addr) goto err_ioremap; - /* hw->hw_addr can be altered, we'll use adapter->io_addr for unmap */ - hw->hw_addr = adapter->io_addr; netdev->netdev_ops = &igb_netdev_ops; igb_set_ethtool_ops(netdev); @@ -2658,7 +2656,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #ifdef CONFIG_PCI_IOV igb_disable_sriov(pdev); #endif - pci_iounmap(pdev, adapter->io_addr); + pci_iounmap(pdev, hw->hw_addr); err_ioremap: free_netdev(netdev); err_alloc_etherdev: @@ -2825,7 +2823,7 @@ static void igb_remove(struct pci_dev *pdev) igb_clear_interrupt_scheme(adapter); - pci_iounmap(pdev, adapter->io_addr); + pci_iounmap(pdev, hw->hw_addr); if (hw->flash_address) iounmap(hw->flash_address); pci_release_selected_regions(pdev, @@ -2858,13 +2856,6 @@ static void igb_probe_vfs(struct igb_adapter *adapter) if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) return; - /* Of the below we really only want the effect of getting - * IGB_FLAG_HAS_MSIX set (if available), without which - * igb_enable_sriov() has no effect. - */ - igb_set_interrupt_capability(adapter, true); - igb_reset_interrupt_capability(adapter); - pci_sriov_set_totalvfs(pdev, 7); igb_enable_sriov(pdev, max_vfs); @@ -3005,8 +2996,6 @@ static int igb_sw_init(struct igb_adapter *adapter) /* Setup and initialize a copy of the hw vlan table array */ adapter->shadow_vfta = kcalloc(E1000_VLAN_FILTER_TBL_SIZE, sizeof(u32), GFP_ATOMIC); - if (!adapter->shadow_vfta) - return -ENOMEM; /* This call may decrease the number of queues */ if (igb_init_interrupt_scheme(adapter, true)) { @@ -3174,9 +3163,7 @@ static int __igb_close(struct net_device *netdev, bool suspending) static int igb_close(struct net_device *netdev) { - if (netif_device_present(netdev) || netdev->dismantle) - return __igb_close(netdev, false); - return 0; + return __igb_close(netdev, false); } /** @@ -6435,7 +6422,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) break; /* prevent any other reads prior to eop_desc */ - smp_rmb(); + read_barrier_depends(); /* if DD is not set pending work has not been completed */ if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) @@ -7329,14 +7316,12 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, int retval = 0; #endif - rtnl_lock(); netif_device_detach(netdev); if (netif_running(netdev)) __igb_close(netdev, true); igb_clear_interrupt_scheme(adapter); - rtnl_unlock(); #ifdef CONFIG_PM retval = pci_save_state(pdev); @@ -7456,15 +7441,16 @@ static int igb_resume(struct device *dev) wr32(E1000_WUS, ~0); - rtnl_lock(); - if (!err && netif_running(netdev)) + if (netdev->flags & IFF_UP) { + rtnl_lock(); err = __igb_open(netdev, true); + rtnl_unlock(); + if (err) + return err; + } - if (!err) - netif_device_attach(netdev); - rtnl_unlock(); - - return err; + netif_device_attach(netdev); + return 0; } static int igb_runtime_idle(struct device *dev) @@ -7663,11 +7649,6 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3cold, 0); - /* In case of PCI error, adapter lose its HW address - * so we should re-assign it here. - */ - hw->hw_addr = adapter->io_addr; - igb_reset(adapter); wr32(E1000_WUS, ~0); result = PCI_ERS_RESULT_RECOVERED; diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 519b72c41888..297af801f051 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -809,7 +809,7 @@ static bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring) break; /* prevent any other reads prior to eop_desc */ - smp_rmb(); + read_barrier_depends(); /* if DD is not set pending work has not been completed */ if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index cd2afe92f1da..ce61b36b94f1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -1814,12 +1814,7 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, if (enable_addr != 0) rar_high |= IXGBE_RAH_AV; - /* Record lower 32 bits of MAC address and then make - * sure that write is flushed to hardware before writing - * the upper 16 bits and setting the valid bit. - */ IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); - IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); return 0; @@ -1851,13 +1846,8 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); - /* Clear the address valid bit and upper 16 bits of the address - * before clearing the lower bits. This way we aren't updating - * a live filter. - */ - IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); - IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); + IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); /* clear VMDq pool/queue selection for this RAR */ hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); @@ -3630,10 +3620,10 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, fw_cmd.ver_build = build; fw_cmd.ver_sub = sub; fw_cmd.hdr.checksum = 0; - fw_cmd.pad = 0; - fw_cmd.pad2 = 0; fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); + fw_cmd.pad = 0; + fw_cmd.pad2 = 0; for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index f0de09db8283..f3168bcc7d87 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -307,7 +307,6 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) ixgbe_cache_ring_rss(adapter); } -#define IXGBE_RSS_64Q_MASK 0x3F #define IXGBE_RSS_16Q_MASK 0xF #define IXGBE_RSS_8Q_MASK 0x7 #define IXGBE_RSS_4Q_MASK 0x3 @@ -603,7 +602,6 @@ static bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter) **/ static bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) { - struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_ring_feature *f; u16 rss_i; @@ -612,11 +610,7 @@ static bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) rss_i = f->limit; f->indices = rss_i; - - if (hw->mac.type < ixgbe_mac_X550) - f->mask = IXGBE_RSS_16Q_MASK; - else - f->mask = IXGBE_RSS_64Q_MASK; + f->mask = IXGBE_RSS_16Q_MASK; /* disable ATR by default, it will be configured below */ adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index a5b443171b8b..aed8d029b23d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1114,7 +1114,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, break; /* prevent any other reads prior to eop_desc */ - smp_rmb(); + read_barrier_depends(); /* if DD is not set pending work has not been completed */ if (!(eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD))) @@ -2786,8 +2786,7 @@ int ixgbe_poll(struct napi_struct *napi, int budget) ixgbe_for_each_ring(ring, q_vector->tx) clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring); - /* Exit if we are called by netpoll or busy polling is active */ - if ((budget <= 0) || !ixgbe_qv_lock_napi(q_vector)) + if (!ixgbe_qv_lock_napi(q_vector)) return budget; /* attempt to distribute budget to each queue fairly, but don't allow @@ -5878,8 +5877,7 @@ static int ixgbe_close(struct net_device *netdev) ixgbe_ptp_stop(adapter); - if (netif_device_present(netdev)) - ixgbe_close_suspend(adapter); + ixgbe_close_suspend(adapter); ixgbe_fdir_filter_exit(adapter); @@ -5924,12 +5922,14 @@ static int ixgbe_resume(struct pci_dev *pdev) if (!err && netif_running(netdev)) err = ixgbe_open(netdev); - - if (!err) - netif_device_attach(netdev); rtnl_unlock(); - return err; + if (err) + return err; + + netif_device_attach(netdev); + + return 0; } #endif /* CONFIG_PM */ @@ -5944,14 +5944,14 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) int retval = 0; #endif - rtnl_lock(); netif_device_detach(netdev); + rtnl_lock(); if (netif_running(netdev)) ixgbe_close_suspend(adapter); + rtnl_unlock(); ixgbe_clear_interrupt_scheme(adapter); - rtnl_unlock(); #ifdef CONFIG_PM retval = pci_save_state(pdev); @@ -9220,7 +9220,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, } if (netif_running(netdev)) - ixgbe_close_suspend(adapter); + ixgbe_down(adapter); if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state)) pci_disable_device(pdev); @@ -9290,12 +9290,10 @@ static void ixgbe_io_resume(struct pci_dev *pdev) } #endif - rtnl_lock(); if (netif_running(netdev)) - ixgbe_open(netdev); + ixgbe_up(adapter); netif_device_attach(netdev); - rtnl_unlock(); } static const struct pci_error_handlers ixgbe_err_handler = { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 48d97cb730d8..fb8673d63806 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -113,7 +113,7 @@ static s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val, bool lock) { u32 swfw_mask = hw->phy.phy_semaphore_mask; - int max_retry = 3; + int max_retry = 10; int retry = 0; u8 csum_byte; u8 high_bits; @@ -1764,8 +1764,6 @@ static s32 ixgbe_read_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset, u32 swfw_mask = hw->phy.phy_semaphore_mask; bool nack = true; - if (hw->mac.type >= ixgbe_mac_X550) - max_retry = 3; if (ixgbe_is_sfp_probe(hw, byte_offset, dev_addr)) max_retry = IXGBE_SFP_DETECT_RETRIES; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index a75f2e3ce86f..ebe0ac950b14 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -564,8 +564,6 @@ static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, /* convert offset from words to bytes */ buffer.address = cpu_to_be32((offset + current_word) * 2); buffer.length = cpu_to_be16(words_to_read * 2); - buffer.pad2 = 0; - buffer.pad3 = 0; status = ixgbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer), @@ -1645,6 +1643,8 @@ static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, return status; reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; + reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ | + IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC); reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 50bbad37d640..592ff237d692 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -312,7 +312,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, break; /* prevent any other reads prior to eop_desc */ - smp_rmb(); + read_barrier_depends(); /* if DD is not set pending work has not been completed */ if (!(eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD))) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 07eabf72c480..d74f5f4e5782 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -900,10 +900,10 @@ static void korina_restart_task(struct work_struct *work) DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR, &lp->rx_dma_regs->dmasm); - napi_disable(&lp->napi); - korina_free_ring(dev); + napi_disable(&lp->napi); + if (korina_init(dev) < 0) { printk(KERN_ERR "%s: cannot restart device\n", dev->name); return; @@ -1064,12 +1064,12 @@ static int korina_close(struct net_device *dev) tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR; writel(tmp, &lp->rx_dma_regs->dmasm); + korina_free_ring(dev); + napi_disable(&lp->napi); cancel_work_sync(&lp->restart_task); - korina_free_ring(dev); - free_irq(lp->rx_irq, dev); free_irq(lp->tx_irq, dev); free_irq(lp->ovr_irq, dev); diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c index c122b3b99cd8..fc2fb25343f4 100644 --- a/drivers/net/ethernet/marvell/mvmdio.c +++ b/drivers/net/ethernet/marvell/mvmdio.c @@ -241,8 +241,7 @@ static int orion_mdio_probe(struct platform_device *pdev) dev->regs + MVMDIO_ERR_INT_MASK); } else if (dev->err_interrupt == -EPROBE_DEFER) { - ret = -EPROBE_DEFER; - goto out_mdio; + return -EPROBE_DEFER; } mutex_init(&dev->lock); diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index ea693bbf56d8..a4ac6fedac75 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -226,7 +226,7 @@ /* Various constants */ /* Coalescing */ -#define MVNETA_TXDONE_COAL_PKTS 0 /* interrupt per packet */ +#define MVNETA_TXDONE_COAL_PKTS 1 #define MVNETA_RX_COAL_PKTS 32 #define MVNETA_RX_COAL_USEC 100 @@ -818,7 +818,6 @@ static void mvneta_port_up(struct mvneta_port *pp) } mvreg_write(pp, MVNETA_TXQ_CMD, q_map); - q_map = 0; /* Enable all initialized RXQs. */ mvreg_write(pp, MVNETA_RXQ_CMD, BIT(rxq_def)); } @@ -915,10 +914,6 @@ static void mvneta_port_disable(struct mvneta_port *pp) val &= ~MVNETA_GMAC0_PORT_ENABLE; mvreg_write(pp, MVNETA_GMAC_CTRL_0, val); - pp->link = 0; - pp->duplex = -1; - pp->speed = 0; - udelay(200); } @@ -2451,7 +2446,7 @@ static void mvneta_start_dev(struct mvneta_port *pp) mvneta_port_enable(pp); /* Enable polling on the port */ - for_each_online_cpu(cpu) { + for_each_present_cpu(cpu) { struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); napi_enable(&port->napi); @@ -2477,7 +2472,7 @@ static void mvneta_stop_dev(struct mvneta_port *pp) phy_stop(pp->phy_dev); - for_each_online_cpu(cpu) { + for_each_present_cpu(cpu) { struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); napi_disable(&port->napi); @@ -2907,11 +2902,13 @@ static int mvneta_open(struct net_device *dev) static int mvneta_stop(struct net_device *dev) { struct mvneta_port *pp = netdev_priv(dev); + int cpu; mvneta_stop_dev(pp); mvneta_mdio_remove(pp); unregister_cpu_notifier(&pp->cpu_notifier); - on_each_cpu(mvneta_percpu_disable, pp, true); + for_each_present_cpu(cpu) + smp_call_function_single(cpu, mvneta_percpu_disable, pp, true); free_percpu_irq(dev->irq, pp->ports); mvneta_cleanup_rxqs(pp); mvneta_cleanup_txqs(pp); diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index ac92685dd4e5..a4beccf1fd46 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -772,17 +772,6 @@ struct mvpp2_rx_desc { u32 reserved8; }; -struct mvpp2_txq_pcpu_buf { - /* Transmitted SKB */ - struct sk_buff *skb; - - /* Physical address of transmitted buffer */ - dma_addr_t phys; - - /* Size transmitted */ - size_t size; -}; - /* Per-CPU Tx queue control */ struct mvpp2_txq_pcpu { int cpu; @@ -798,8 +787,11 @@ struct mvpp2_txq_pcpu { /* Number of Tx DMA descriptors reserved for each CPU */ int reserved_num; - /* Infos about transmitted buffers */ - struct mvpp2_txq_pcpu_buf *buffs; + /* Array of transmitted skb */ + struct sk_buff **tx_skb; + + /* Array of transmitted buffers' physical addresses */ + dma_addr_t *tx_buffs; /* Index of last TX DMA descriptor that was inserted */ int txq_put_index; @@ -989,11 +981,10 @@ static void mvpp2_txq_inc_put(struct mvpp2_txq_pcpu *txq_pcpu, struct sk_buff *skb, struct mvpp2_tx_desc *tx_desc) { - struct mvpp2_txq_pcpu_buf *tx_buf = - txq_pcpu->buffs + txq_pcpu->txq_put_index; - tx_buf->skb = skb; - tx_buf->size = tx_desc->data_size; - tx_buf->phys = tx_desc->buf_phys_addr + tx_desc->packet_offset; + txq_pcpu->tx_skb[txq_pcpu->txq_put_index] = skb; + if (skb) + txq_pcpu->tx_buffs[txq_pcpu->txq_put_index] = + tx_desc->buf_phys_addr; txq_pcpu->txq_put_index++; if (txq_pcpu->txq_put_index == txq_pcpu->size) txq_pcpu->txq_put_index = 0; @@ -4412,15 +4403,17 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port, int i; for (i = 0; i < num; i++) { - struct mvpp2_txq_pcpu_buf *tx_buf = - txq_pcpu->buffs + txq_pcpu->txq_get_index; - - dma_unmap_single(port->dev->dev.parent, tx_buf->phys, - tx_buf->size, DMA_TO_DEVICE); - if (tx_buf->skb) - dev_kfree_skb_any(tx_buf->skb); + dma_addr_t buf_phys_addr = + txq_pcpu->tx_buffs[txq_pcpu->txq_get_index]; + struct sk_buff *skb = txq_pcpu->tx_skb[txq_pcpu->txq_get_index]; mvpp2_txq_inc_get(txq_pcpu); + + dma_unmap_single(port->dev->dev.parent, buf_phys_addr, + skb_headlen(skb), DMA_TO_DEVICE); + if (!skb) + continue; + dev_kfree_skb_any(skb); } } @@ -4671,10 +4664,15 @@ static int mvpp2_txq_init(struct mvpp2_port *port, for_each_present_cpu(cpu) { txq_pcpu = per_cpu_ptr(txq->pcpu, cpu); txq_pcpu->size = txq->size; - txq_pcpu->buffs = kmalloc(txq_pcpu->size * - sizeof(struct mvpp2_txq_pcpu_buf), - GFP_KERNEL); - if (!txq_pcpu->buffs) + txq_pcpu->tx_skb = kmalloc(txq_pcpu->size * + sizeof(*txq_pcpu->tx_skb), + GFP_KERNEL); + if (!txq_pcpu->tx_skb) + goto error; + + txq_pcpu->tx_buffs = kmalloc(txq_pcpu->size * + sizeof(dma_addr_t), GFP_KERNEL); + if (!txq_pcpu->tx_buffs) goto error; txq_pcpu->count = 0; @@ -4688,7 +4686,8 @@ static int mvpp2_txq_init(struct mvpp2_port *port, error: for_each_present_cpu(cpu) { txq_pcpu = per_cpu_ptr(txq->pcpu, cpu); - kfree(txq_pcpu->buffs); + kfree(txq_pcpu->tx_skb); + kfree(txq_pcpu->tx_buffs); } dma_free_coherent(port->dev->dev.parent, @@ -4707,7 +4706,8 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port, for_each_present_cpu(cpu) { txq_pcpu = per_cpu_ptr(txq->pcpu, cpu); - kfree(txq_pcpu->buffs); + kfree(txq_pcpu->tx_skb); + kfree(txq_pcpu->tx_buffs); } if (txq->descs) @@ -5666,7 +5666,6 @@ static void mvpp2_set_rx_mode(struct net_device *dev) int id = port->id; bool allmulti = dev->flags & IFF_ALLMULTI; -retry: mvpp2_prs_mac_promisc_set(priv, id, dev->flags & IFF_PROMISC); mvpp2_prs_mac_multi_set(priv, id, MVPP2_PE_MAC_MC_ALL, allmulti); mvpp2_prs_mac_multi_set(priv, id, MVPP2_PE_MAC_MC_IP6, allmulti); @@ -5674,13 +5673,9 @@ static void mvpp2_set_rx_mode(struct net_device *dev) /* Remove all port->id's mcast enries */ mvpp2_prs_mcast_del_all(priv, id); - if (!allmulti) { - netdev_for_each_mc_addr(ha, dev) { - if (mvpp2_prs_mac_da_accept(priv, id, ha->addr, true)) { - allmulti = true; - goto retry; - } - } + if (allmulti && !netdev_mc_empty(dev)) { + netdev_for_each_mc_addr(ha, dev) + mvpp2_prs_mac_da_accept(priv, id, ha->addr, true); } } diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 6e5065f0907b..5606a043063e 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -5079,7 +5079,7 @@ static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&hw->restart_work, sky2_restart); pci_set_drvdata(pdev, hw); - pdev->d3_delay = 200; + pdev->d3_delay = 150; return 0; @@ -5220,19 +5220,6 @@ static SIMPLE_DEV_PM_OPS(sky2_pm_ops, sky2_suspend, sky2_resume); static void sky2_shutdown(struct pci_dev *pdev) { - struct sky2_hw *hw = pci_get_drvdata(pdev); - int port; - - for (port = 0; port < hw->ports; port++) { - struct net_device *ndev = hw->dev[port]; - - rtnl_lock(); - if (netif_running(ndev)) { - dev_close(ndev); - netif_device_detach(ndev); - } - rtnl_unlock(); - } sky2_suspend(&pdev->dev); pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev)); pci_set_power_state(pdev, PCI_D3hot); diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c index e203d0c4e5a3..715de8affcc9 100644 --- a/drivers/net/ethernet/mellanox/mlx4/catas.c +++ b/drivers/net/ethernet/mellanox/mlx4/catas.c @@ -158,7 +158,7 @@ static int mlx4_reset_slave(struct mlx4_dev *dev) return -ETIMEDOUT; } -int mlx4_comm_internal_err(u32 slave_read) +static int mlx4_comm_internal_err(u32 slave_read) { return (u32)COMM_CHAN_EVENT_INTERNAL_ERR == (slave_read & (u32)COMM_CHAN_EVENT_INTERNAL_ERR) ? 1 : 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index fc222df47aa9..d48d5793407d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -2278,17 +2278,6 @@ static int sync_toggles(struct mlx4_dev *dev) rd_toggle = swab32(readl(&priv->mfunc.comm->slave_read)); if (wr_toggle == 0xffffffff || rd_toggle == 0xffffffff) { /* PCI might be offline */ - - /* If device removal has been requested, - * do not continue retrying. - */ - if (dev->persist->interface_state & - MLX4_INTERFACE_STATE_NOWAIT) { - mlx4_warn(dev, - "communication channel is offline\n"); - return -EIO; - } - msleep(100); wr_toggle = swab32(readl(&priv->mfunc.comm-> slave_write)); diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c index 6eba58044456..3348e646db70 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/cq.c @@ -101,19 +101,13 @@ void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn) { struct mlx4_cq *cq; - rcu_read_lock(); cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree, cqn & (dev->caps.num_cqs - 1)); - rcu_read_unlock(); - if (!cq) { mlx4_dbg(dev, "Completion event for bogus CQ %08x\n", cqn); return; } - /* Acessing the CQ outside of rcu_read_lock is safe, because - * the CQ is freed only after interrupt handling is completed. - */ ++cq->arm_sn; cq->comp(cq); @@ -124,19 +118,23 @@ void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type) struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table; struct mlx4_cq *cq; - rcu_read_lock(); + spin_lock(&cq_table->lock); + cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1)); - rcu_read_unlock(); + if (cq) + atomic_inc(&cq->refcount); + + spin_unlock(&cq_table->lock); if (!cq) { - mlx4_dbg(dev, "Async event for bogus CQ %08x\n", cqn); + mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn); return; } - /* Acessing the CQ outside of rcu_read_lock is safe, because - * the CQ is freed only after interrupt handling is completed. - */ cq->event(cq, event_type); + + if (atomic_dec_and_test(&cq->refcount)) + complete(&cq->free); } static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, @@ -303,9 +301,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, if (err) return err; - spin_lock(&cq_table->lock); + spin_lock_irq(&cq_table->lock); err = radix_tree_insert(&cq_table->tree, cq->cqn, cq); - spin_unlock(&cq_table->lock); + spin_unlock_irq(&cq_table->lock); if (err) goto err_icm; @@ -349,9 +347,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, return 0; err_radix: - spin_lock(&cq_table->lock); + spin_lock_irq(&cq_table->lock); radix_tree_delete(&cq_table->tree, cq->cqn); - spin_unlock(&cq_table->lock); + spin_unlock_irq(&cq_table->lock); err_icm: mlx4_cq_free_icm(dev, cq->cqn); @@ -370,15 +368,15 @@ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq) if (err) mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn); - spin_lock(&cq_table->lock); - radix_tree_delete(&cq_table->tree, cq->cqn); - spin_unlock(&cq_table->lock); - synchronize_irq(priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq); if (priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq != priv->eq_table.eq[MLX4_EQ_ASYNC].irq) synchronize_irq(priv->eq_table.eq[MLX4_EQ_ASYNC].irq); + spin_lock_irq(&cq_table->lock); + radix_tree_delete(&cq_table->tree, cq->cqn); + spin_unlock_irq(&cq_table->lock); + if (atomic_dec_and_test(&cq->refcount)) complete(&cq->free); wait_for_completion(&cq->free); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c index 4dccf7287f0f..1494997c4f7e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c @@ -88,17 +88,10 @@ void mlx4_en_remove_timestamp(struct mlx4_en_dev *mdev) } } -#define MLX4_EN_WRAP_AROUND_SEC 10UL -/* By scheduling the overflow check every 5 seconds, we have a reasonably - * good chance we wont miss a wrap around. - * TOTO: Use a timer instead of a work queue to increase the guarantee. - */ -#define MLX4_EN_OVERFLOW_PERIOD (MLX4_EN_WRAP_AROUND_SEC * HZ / 2) - void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev) { bool timeout = time_is_before_jiffies(mdev->last_overflow_check + - MLX4_EN_OVERFLOW_PERIOD); + mdev->overflow_period); unsigned long flags; if (timeout) { @@ -243,6 +236,7 @@ static const struct ptp_clock_info mlx4_en_ptp_clock_info = { .enable = mlx4_en_phc_enable, }; +#define MLX4_EN_WRAP_AROUND_SEC 10ULL /* This function calculates the max shift that enables the user range * of MLX4_EN_WRAP_AROUND_SEC values in the cycles register. @@ -264,6 +258,7 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) { struct mlx4_dev *dev = mdev->dev; unsigned long flags; + u64 ns, zero = 0; /* mlx4_en_init_timestamp is called for each netdev. * mdev->ptp_clock is common for all ports, skip initialization if @@ -287,6 +282,13 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) ktime_to_ns(ktime_get_real())); write_unlock_irqrestore(&mdev->clock_lock, flags); + /* Calculate period in seconds to call the overflow watchdog - to make + * sure counter is checked at least once every wrap around. + */ + ns = cyclecounter_cyc2ns(&mdev->cycles, mdev->cycles.mask, zero, &zero); + do_div(ns, NSEC_PER_SEC / 2 / HZ); + mdev->overflow_period = ns; + /* Configure the PHC */ mdev->ptp_clock_info = mlx4_en_ptp_clock_info; snprintf(mdev->ptp_clock_info.name, 16, "mlx4 ptp"); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index bcfac000199e..ddb5541882f5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -967,22 +967,6 @@ static int mlx4_en_set_coalesce(struct net_device *dev, if (!coal->tx_max_coalesced_frames_irq) return -EINVAL; - if (coal->tx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME || - coal->rx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME || - coal->rx_coalesce_usecs_low > MLX4_EN_MAX_COAL_TIME || - coal->rx_coalesce_usecs_high > MLX4_EN_MAX_COAL_TIME) { - netdev_info(dev, "%s: maximum coalesce time supported is %d usecs\n", - __func__, MLX4_EN_MAX_COAL_TIME); - return -ERANGE; - } - - if (coal->tx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS || - coal->rx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS) { - netdev_info(dev, "%s: maximum coalesced frames supported is %d\n", - __func__, MLX4_EN_MAX_COAL_PKTS); - return -ERANGE; - } - priv->rx_frames = (coal->rx_max_coalesced_frames == MLX4_EN_AUTO_CONF) ? MLX4_EN_RX_COAL_TARGET : diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 232191417b93..67e9633ea9c7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2282,7 +2282,7 @@ static int mlx4_en_set_vf_mac(struct net_device *dev, int queue, u8 *mac) struct mlx4_en_dev *mdev = en_priv->mdev; u64 mac_u64 = mlx4_mac_to_u64(mac); - if (is_multicast_ether_addr(mac)) + if (!is_valid_ether_addr(mac)) return -EINVAL; return mlx4_set_vf_mac(mdev->dev, en_priv->port, queue, mac_u64); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 82bf1b539d87..bbff8ec6713e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -439,14 +439,8 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv) ring->cqn = priv->rx_cq[ring_ind]->mcq.cqn; ring->stride = stride; - if (ring->stride <= TXBB_SIZE) { - /* Stamp first unused send wqe */ - __be32 *ptr = (__be32 *)ring->buf; - __be32 stamp = cpu_to_be32(1 << STAMP_SHIFT); - *ptr = stamp; - /* Move pointer to start of rx section */ + if (ring->stride <= TXBB_SIZE) ring->buf += TXBB_SIZE; - } ring->log_stride = ffs(ring->stride) - 1; ring->buf_size = ring->size * ring->stride; @@ -508,11 +502,8 @@ void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv) return; for (ring = 0; ring < priv->rx_ring_num; ring++) { - if (mlx4_en_is_ring_empty(priv->rx_ring[ring])) { - local_bh_disable(); + if (mlx4_en_is_ring_empty(priv->rx_ring[ring])) napi_reschedule(&priv->rx_cq[ring]->napi); - local_bh_enable(); - } } } diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index ff77b8b608bd..603d1c3d3b2e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -542,9 +542,8 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) break; case MLX4_EVENT_TYPE_SRQ_LIMIT: - mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT. srq_no=0x%x, eq 0x%x\n", - __func__, be32_to_cpu(eqe->event.srq.srqn), - eq->eqn); + mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n", + __func__); case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR: if (mlx4_is_master(dev)) { /* forward only to slave owning the SRQ */ @@ -559,19 +558,15 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) eq->eqn, eq->cons_index, ret); break; } - if (eqe->type == - MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) - mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n", - __func__, slave, - be32_to_cpu(eqe->event.srq.srqn), - eqe->type, eqe->subtype); + mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n", + __func__, slave, + be32_to_cpu(eqe->event.srq.srqn), + eqe->type, eqe->subtype); if (!ret && slave != dev->caps.function) { - if (eqe->type == - MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) - mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n", - __func__, eqe->type, - eqe->subtype, slave); + mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n", + __func__, eqe->type, + eqe->subtype, slave); mlx4_slave_event(dev, slave, eqe); break; } diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c index e1f9e7cebf8f..2a9dd460a95f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -118,13 +118,8 @@ static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem, if (!buf) return -ENOMEM; - if (offset_in_page(buf)) { - dma_free_coherent(dev, PAGE_SIZE << order, - buf, sg_dma_address(mem)); - return -ENOMEM; - } - sg_set_buf(mem, buf, PAGE_SIZE << order); + BUG_ON(mem->offset); sg_dma_len(mem) = PAGE_SIZE << order; return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index 1a134e08f010..0472941af820 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -218,18 +218,6 @@ void mlx4_unregister_device(struct mlx4_dev *dev) struct mlx4_interface *intf; mlx4_stop_catas_poll(dev); - if (dev->persist->interface_state & MLX4_INTERFACE_STATE_DELETION && - mlx4_is_slave(dev)) { - /* In mlx4_remove_one on a VF */ - u32 slave_read = - swab32(readl(&mlx4_priv(dev)->mfunc.comm->slave_read)); - - if (mlx4_comm_internal_err(slave_read)) { - mlx4_dbg(dev, "%s: comm channel is down, entering error state.\n", - __func__); - mlx4_enter_error_state(dev->persist); - } - } mutex_lock(&intf_mutex); list_for_each_entry(intf, &intf_list, list) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index a7d3144c2388..31c491e02e69 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -791,6 +791,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) return -ENOSYS; } + mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz; + dev->caps.hca_core_clock = hca_param.hca_core_clock; memset(&dev_cap, 0, sizeof(dev_cap)); @@ -1763,14 +1765,6 @@ static int mlx4_comm_check_offline(struct mlx4_dev *dev) (u32)(1 << COMM_CHAN_OFFLINE_OFFSET)); if (!offline_bit) return 0; - - /* If device removal has been requested, - * do not continue retrying. - */ - if (dev->persist->interface_state & - MLX4_INTERFACE_STATE_NOWAIT) - break; - /* There are cases as part of AER/Reset flow that PF needs * around 100 msec to load. We therefore sleep for 100 msec * to allow other tasks to make use of that CPU during this @@ -3698,9 +3692,6 @@ static void mlx4_remove_one(struct pci_dev *pdev) struct mlx4_priv *priv = mlx4_priv(dev); int active_vfs = 0; - if (mlx4_is_slave(dev)) - persist->interface_state |= MLX4_INTERFACE_STATE_NOWAIT; - mutex_lock(&persist->interface_state_mutex); persist->interface_state |= MLX4_INTERFACE_STATE_DELETION; mutex_unlock(&persist->interface_state_mutex); diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index 897d061e4f03..1d4e2e054647 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -35,7 +35,6 @@ #include #include -#include #include #include "mlx4.h" @@ -986,21 +985,16 @@ int mlx4_flow_attach(struct mlx4_dev *dev, if (IS_ERR(mailbox)) return PTR_ERR(mailbox); - if (!mlx4_qp_lookup(dev, rule->qpn)) { - mlx4_err_rule(dev, "QP doesn't exist\n", rule); - ret = -EINVAL; - goto out; - } - trans_rule_ctrl_to_hw(rule, mailbox->buf); size += sizeof(struct mlx4_net_trans_rule_hw_ctrl); list_for_each_entry(cur, &rule->list, list) { ret = parse_trans_rule(dev, cur, mailbox->buf + size); - if (ret < 0) - goto out; - + if (ret < 0) { + mlx4_free_cmd_mailbox(dev, mailbox); + return ret; + } size += ret; } @@ -1027,7 +1021,6 @@ int mlx4_flow_attach(struct mlx4_dev *dev, } } -out: mlx4_free_cmd_mailbox(dev, mailbox); return ret; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index f5fdbd53d052..e1cf9036af22 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -1205,7 +1205,6 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type); void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type); void mlx4_enter_error_state(struct mlx4_dev_persistent *persist); -int mlx4_comm_internal_err(u32 slave_read); int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port, enum mlx4_port_type *type); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 607daaffae98..c41f15102ae0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -140,9 +140,6 @@ enum { #define MLX4_EN_TX_COAL_PKTS 16 #define MLX4_EN_TX_COAL_TIME 0x10 -#define MLX4_EN_MAX_COAL_PKTS U16_MAX -#define MLX4_EN_MAX_COAL_TIME U16_MAX - #define MLX4_EN_RX_RATE_LOW 400000 #define MLX4_EN_RX_COAL_TIME_LOW 0 #define MLX4_EN_RX_RATE_HIGH 450000 @@ -412,6 +409,7 @@ struct mlx4_en_dev { struct cyclecounter cycles; struct timecounter clock; unsigned long last_overflow_check; + unsigned long overflow_period; struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_clock_info; struct notifier_block nb; @@ -521,8 +519,8 @@ struct mlx4_en_priv { u16 rx_usecs_low; u32 pkt_rate_high; u16 rx_usecs_high; - u32 sample_interval; - u32 adaptive_rx_coal; + u16 sample_interval; + u16 adaptive_rx_coal; u32 msg_enable; u32 loopback_ok; u32 validate_loopback; diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index d6d87dd8a28f..168823dde79f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -280,9 +280,6 @@ void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) u64 in_param = 0; int err; - if (!cnt) - return; - if (mlx4_is_mfunc(dev)) { set_param_l(&in_param, base_qpn); set_param_h(&in_param, cnt); @@ -381,19 +378,6 @@ static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn) __mlx4_qp_free_icm(dev, qpn); } -struct mlx4_qp *mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn) -{ - struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; - struct mlx4_qp *qp; - - spin_lock_irq(&qp_table->lock); - - qp = __mlx4_qp_lookup(dev, qpn); - - spin_unlock_irq(&qp_table->lock); - return qp; -} - int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp, gfp_t gfp) { struct mlx4_priv *priv = mlx4_priv(dev); @@ -481,12 +465,6 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, } if (attr & MLX4_UPDATE_QP_QOS_VPORT) { - if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QOS_VPP)) { - mlx4_warn(dev, "Granular QoS per VF is not enabled\n"); - err = -EOPNOTSUPP; - goto out; - } - qp_mask |= 1ULL << MLX4_UPD_QP_MASK_QOS_VPP; cmd->qp_context.qos_vport = params->qos_vport; } diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 7911dc3da98e..d314d96dcb1c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -2891,7 +2891,7 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave, u32 srqn = qp_get_srqn(qpc) & 0xffffff; int use_srq = (qp_get_srqn(qpc) >> 24) & 1; struct res_srq *srq; - int local_qpn = vhcr->in_modifier & 0xffffff; + int local_qpn = be32_to_cpu(qpc->local_qpn) & 0xffffff; err = adjust_qp_sched_queue(dev, slave, qpc, inbox); if (err) @@ -2955,9 +2955,6 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave, put_res(dev, slave, srqn, RES_SRQ); qp->srq = srq; } - - /* Save param3 for dynamic changes from VST back to VGT */ - qp->param3 = qpc->param3; put_res(dev, slave, rcqn, RES_CQ); put_res(dev, slave, mtt_base, RES_MTT); res_end_move(dev, slave, RES_QP, qpn); @@ -3750,6 +3747,7 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave, int qpn = vhcr->in_modifier & 0x7fffff; struct res_qp *qp; u8 orig_sched_queue; + __be32 orig_param3 = qpc->param3; u8 orig_vlan_control = qpc->pri_path.vlan_control; u8 orig_fvl_rx = qpc->pri_path.fvl_rx; u8 orig_pri_path_fl = qpc->pri_path.fl; @@ -3791,6 +3789,7 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave, */ if (!err) { qp->sched_queue = orig_sched_queue; + qp->param3 = orig_param3; qp->vlan_control = orig_vlan_control; qp->fvl_rx = orig_fvl_rx; qp->pri_path_fl = orig_pri_path_fl; @@ -5040,13 +5039,6 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); } -static void update_qos_vpp(struct mlx4_update_qp_context *ctx, - struct mlx4_vf_immed_vlan_work *work) -{ - ctx->qp_mask |= cpu_to_be64(1ULL << MLX4_UPD_QP_MASK_QOS_VPP); - ctx->qp_context.qos_vport = work->qos_vport; -} - void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work) { struct mlx4_vf_immed_vlan_work *work = @@ -5151,10 +5143,11 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work) qp->sched_queue & 0xC7; upd_context->qp_context.pri_path.sched_queue |= ((work->qos & 0x7) << 3); - - if (dev->caps.flags2 & - MLX4_DEV_CAP_FLAG2_QOS_VPP) - update_qos_vpp(upd_context, work); + upd_context->qp_mask |= + cpu_to_be64(1ULL << + MLX4_UPD_QP_MASK_QOS_VPP); + upd_context->qp_context.qos_vport = + work->qos_vport; } err = mlx4_cmd(dev, mailbox->dma, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 9ac14df0ca3b..037fc4cdf5af 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -143,14 +143,13 @@ static struct mlx5_cmd_layout *get_inst(struct mlx5_cmd *cmd, int idx) return cmd->cmd_buf + (idx << cmd->log_stride); } -static u8 xor8_buf(void *buf, size_t offset, int len) +static u8 xor8_buf(void *buf, int len) { u8 *ptr = buf; u8 sum = 0; int i; - int end = len + offset; - for (i = offset; i < end; i++) + for (i = 0; i < len; i++) sum ^= ptr[i]; return sum; @@ -158,49 +157,41 @@ static u8 xor8_buf(void *buf, size_t offset, int len) static int verify_block_sig(struct mlx5_cmd_prot_block *block) { - size_t rsvd0_off = offsetof(struct mlx5_cmd_prot_block, rsvd0); - int xor_len = sizeof(*block) - sizeof(block->data) - 1; - - if (xor8_buf(block, rsvd0_off, xor_len) != 0xff) + if (xor8_buf(block->rsvd0, sizeof(*block) - sizeof(block->data) - 1) != 0xff) return -EINVAL; - if (xor8_buf(block, 0, sizeof(*block)) != 0xff) + if (xor8_buf(block, sizeof(*block)) != 0xff) return -EINVAL; return 0; } -static void calc_block_sig(struct mlx5_cmd_prot_block *block) +static void calc_block_sig(struct mlx5_cmd_prot_block *block, u8 token, + int csum) { - int ctrl_xor_len = sizeof(*block) - sizeof(block->data) - 2; - size_t rsvd0_off = offsetof(struct mlx5_cmd_prot_block, rsvd0); - - block->ctrl_sig = ~xor8_buf(block, rsvd0_off, ctrl_xor_len); - block->sig = ~xor8_buf(block, 0, sizeof(*block) - 1); + block->token = token; + if (csum) { + block->ctrl_sig = ~xor8_buf(block->rsvd0, sizeof(*block) - + sizeof(block->data) - 2); + block->sig = ~xor8_buf(block, sizeof(*block) - 1); + } } -static void calc_chain_sig(struct mlx5_cmd_msg *msg) +static void calc_chain_sig(struct mlx5_cmd_msg *msg, u8 token, int csum) { struct mlx5_cmd_mailbox *next = msg->next; - int size = msg->len; - int blen = size - min_t(int, sizeof(msg->first.data), size); - int n = (blen + MLX5_CMD_DATA_BLOCK_SIZE - 1) - / MLX5_CMD_DATA_BLOCK_SIZE; - int i = 0; - - for (i = 0; i < n && next; i++) { - calc_block_sig(next->buf); + + while (next) { + calc_block_sig(next->buf, token, csum); next = next->next; } } static void set_signature(struct mlx5_cmd_work_ent *ent, int csum) { - ent->lay->sig = ~xor8_buf(ent->lay, 0, sizeof(*ent->lay)); - if (csum) { - calc_chain_sig(ent->in); - calc_chain_sig(ent->out); - } + ent->lay->sig = ~xor8_buf(ent->lay, sizeof(*ent->lay)); + calc_chain_sig(ent->in, ent->token, csum); + calc_chain_sig(ent->out, ent->token, csum); } static void poll_timeout(struct mlx5_cmd_work_ent *ent) @@ -231,17 +222,12 @@ static int verify_signature(struct mlx5_cmd_work_ent *ent) struct mlx5_cmd_mailbox *next = ent->out->next; int err; u8 sig; - int size = ent->out->len; - int blen = size - min_t(int, sizeof(ent->out->first.data), size); - int n = (blen + MLX5_CMD_DATA_BLOCK_SIZE - 1) - / MLX5_CMD_DATA_BLOCK_SIZE; - int i = 0; - sig = xor8_buf(ent->lay, 0, sizeof(*ent->lay)); + sig = xor8_buf(ent->lay, sizeof(*ent->lay)); if (sig != 0xff) return -EINVAL; - for (i = 0; i < n && next; i++) { + while (next) { err = verify_block_sig(next->buf); if (err) return err; @@ -630,10 +616,6 @@ static void dump_command(struct mlx5_core_dev *dev, pr_debug("\n"); } -static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg); -static void mlx5_free_cmd_msg(struct mlx5_core_dev *dev, - struct mlx5_cmd_msg *msg); - static void cmd_work_handler(struct work_struct *work) { struct mlx5_cmd_work_ent *ent = container_of(work, struct mlx5_cmd_work_ent, work); @@ -642,28 +624,16 @@ static void cmd_work_handler(struct work_struct *work) struct mlx5_cmd_layout *lay; struct semaphore *sem; unsigned long flags; - int alloc_ret; - int cmd_mode; sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem; down(sem); if (!ent->page_queue) { - alloc_ret = alloc_ent(cmd); - if (alloc_ret < 0) { - if (ent->callback) { - ent->callback(-EAGAIN, ent->context); - mlx5_free_cmd_msg(dev, ent->out); - free_msg(dev, ent->in); - free_cmd(ent); - } else { - ent->ret = -EAGAIN; - complete(&ent->done); - } + ent->idx = alloc_ent(cmd); + if (ent->idx < 0) { mlx5_core_err(dev, "failed to allocate command entry\n"); up(sem); return; } - ent->idx = alloc_ret; } else { ent->idx = cmd->max_reg_cmds; spin_lock_irqsave(&cmd->alloc_lock, flags); @@ -671,6 +641,7 @@ static void cmd_work_handler(struct work_struct *work) spin_unlock_irqrestore(&cmd->alloc_lock, flags); } + ent->token = alloc_token(cmd); cmd->ent_arr[ent->idx] = ent; lay = get_inst(cmd, ent->idx); ent->lay = lay; @@ -689,7 +660,6 @@ static void cmd_work_handler(struct work_struct *work) set_signature(ent, !cmd->checksum_disabled); dump_command(dev, ent, 1); ent->ts1 = ktime_get_ns(); - cmd_mode = cmd->mode; /* ring doorbell after the descriptor is valid */ mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx); @@ -697,7 +667,7 @@ static void cmd_work_handler(struct work_struct *work) iowrite32be(1 << ent->idx, &dev->iseg->cmd_dbell); mmiowb(); /* if not in polling don't use ent after this point */ - if (cmd_mode == CMD_MODE_POLLING) { + if (cmd->mode == CMD_MODE_POLLING) { poll_timeout(ent); /* make sure we read the descriptor after ownership is SW */ rmb(); @@ -785,8 +755,7 @@ static u8 *get_status_ptr(struct mlx5_outbox_hdr *out) static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, struct mlx5_cmd_msg *out, void *uout, int uout_size, mlx5_cmd_cbk_t callback, - void *context, int page_queue, u8 *status, - u8 token) + void *context, int page_queue, u8 *status) { struct mlx5_cmd *cmd = &dev->cmd; struct mlx5_cmd_work_ent *ent; @@ -803,8 +772,6 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, if (IS_ERR(ent)) return PTR_ERR(ent); - ent->token = token; - if (!callback) init_completion(&ent->done); @@ -877,8 +844,7 @@ static const struct file_operations fops = { .write = dbg_write, }; -static int mlx5_copy_to_msg(struct mlx5_cmd_msg *to, void *from, int size, - u8 token) +static int mlx5_copy_to_msg(struct mlx5_cmd_msg *to, void *from, int size) { struct mlx5_cmd_prot_block *block; struct mlx5_cmd_mailbox *next; @@ -904,7 +870,6 @@ static int mlx5_copy_to_msg(struct mlx5_cmd_msg *to, void *from, int size, memcpy(block->data, from, copy); from += copy; size -= copy; - block->token = token; next = next->next; } @@ -974,8 +939,7 @@ static void free_cmd_box(struct mlx5_core_dev *dev, } static struct mlx5_cmd_msg *mlx5_alloc_cmd_msg(struct mlx5_core_dev *dev, - gfp_t flags, int size, - u8 token) + gfp_t flags, int size) { struct mlx5_cmd_mailbox *tmp, *head = NULL; struct mlx5_cmd_prot_block *block; @@ -1004,7 +968,6 @@ static struct mlx5_cmd_msg *mlx5_alloc_cmd_msg(struct mlx5_core_dev *dev, tmp->next = head; block->next = cpu_to_be64(tmp->next ? tmp->next->dma : 0); block->block_num = cpu_to_be32(n - i - 1); - block->token = token; head = tmp; } msg->next = head; @@ -1128,7 +1091,7 @@ static ssize_t outlen_write(struct file *filp, const char __user *buf, { struct mlx5_core_dev *dev = filp->private_data; struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; - char outlen_str[8] = {0}; + char outlen_str[8]; int outlen; void *ptr; int err; @@ -1143,6 +1106,8 @@ static ssize_t outlen_write(struct file *filp, const char __user *buf, if (copy_from_user(outlen_str, buf, count)) return -EFAULT; + outlen_str[7] = 0; + err = sscanf(outlen_str, "%d", &outlen); if (err < 0) return err; @@ -1386,7 +1351,7 @@ static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size, } if (IS_ERR(msg)) - msg = mlx5_alloc_cmd_msg(dev, gfp, in_size, 0); + msg = mlx5_alloc_cmd_msg(dev, gfp, in_size); return msg; } @@ -1411,7 +1376,6 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int err; u8 status = 0; u32 drv_synd; - u8 token; if (pci_channel_offline(dev->pdev) || dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { @@ -1430,22 +1394,20 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, return err; } - token = alloc_token(&dev->cmd); - - err = mlx5_copy_to_msg(inb, in, in_size, token); + err = mlx5_copy_to_msg(inb, in, in_size); if (err) { mlx5_core_warn(dev, "err %d\n", err); goto out_in; } - outb = mlx5_alloc_cmd_msg(dev, gfp, out_size, token); + outb = mlx5_alloc_cmd_msg(dev, gfp, out_size); if (IS_ERR(outb)) { err = PTR_ERR(outb); goto out_in; } err = mlx5_cmd_invoke(dev, inb, outb, out, out_size, callback, context, - pages_queue, &status, token); + pages_queue, &status); if (err) goto out_out; @@ -1513,7 +1475,7 @@ static int create_msg_cache(struct mlx5_core_dev *dev) INIT_LIST_HEAD(&cmd->cache.med.head); for (i = 0; i < NUM_LONG_LISTS; i++) { - msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, LONG_LIST_SIZE, 0); + msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, LONG_LIST_SIZE); if (IS_ERR(msg)) { err = PTR_ERR(msg); goto ex_err; @@ -1523,7 +1485,7 @@ static int create_msg_cache(struct mlx5_core_dev *dev) } for (i = 0; i < NUM_MED_LISTS; i++) { - msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, MED_LIST_SIZE, 0); + msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, MED_LIST_SIZE); if (IS_ERR(msg)) { err = PTR_ERR(msg); goto ex_err; @@ -1623,7 +1585,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) cmd->checksum_disabled = 1; cmd->max_reg_cmds = (1 << cmd->log_sz) - 1; - cmd->bitmask = (1UL << cmd->max_reg_cmds) - 1; + cmd->bitmask = (1 << cmd->max_reg_cmds) - 1; cmd->cmdif_rev = ioread32be(&dev->iseg->cmdif_rev_fw_sub) >> 16; if (cmd->cmdif_rev > CMD_IF_REV) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 7cc9df717323..2e022e900939 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -399,9 +399,6 @@ static int mlx5e_get_coalesce(struct net_device *netdev, { struct mlx5e_priv *priv = netdev_priv(netdev); - if (!MLX5_CAP_GEN(priv->mdev, cq_moderation)) - return -ENOTSUPP; - coal->rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; coal->rx_max_coalesced_frames = priv->params.rx_cq_moderation_pkts; coal->tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; @@ -419,18 +416,11 @@ static int mlx5e_set_coalesce(struct net_device *netdev, int tc; int i; - if (!MLX5_CAP_GEN(mdev, cq_moderation)) - return -ENOTSUPP; - - mutex_lock(&priv->state_lock); priv->params.tx_cq_moderation_usec = coal->tx_coalesce_usecs; priv->params.tx_cq_moderation_pkts = coal->tx_max_coalesced_frames; priv->params.rx_cq_moderation_usec = coal->rx_coalesce_usecs; priv->params.rx_cq_moderation_pkts = coal->rx_max_coalesced_frames; - if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) - goto out; - for (i = 0; i < priv->params.num_channels; ++i) { c = priv->channel[i]; @@ -446,8 +436,6 @@ static int mlx5e_set_coalesce(struct net_device *netdev, coal->rx_max_coalesced_frames); } -out: - mutex_unlock(&priv->state_lock); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 90e876ecc720..cbd17e25beeb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -863,10 +863,12 @@ static int mlx5e_open_cq(struct mlx5e_channel *c, if (err) goto err_destroy_cq; - if (MLX5_CAP_GEN(mdev, cq_moderation)) - mlx5_core_modify_cq_moderation(mdev, &cq->mcq, - moderation_usecs, - moderation_frames); + err = mlx5_core_modify_cq_moderation(mdev, &cq->mcq, + moderation_usecs, + moderation_frames); + if (err) + goto err_destroy_cq; + return 0; err_destroy_cq: @@ -1961,8 +1963,6 @@ static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev) } if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable)) mlx5_core_warn(mdev, "Self loop back prevention is not supported\n"); - if (!MLX5_CAP_GEN(mdev, cq_moderation)) - mlx5_core_warn(mdev, "CQ modiration is not supported\n"); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index e9408f5e2a1d..cf0098596e85 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -197,10 +197,6 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, if (lro_num_seg > 1) { mlx5e_lro_update_hdr(skb, cqe); skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt, lro_num_seg); - /* Subtract one since we already counted this as one - * "regular" packet in mlx5e_complete_rx_cqe() - */ - rq->stats.packets += lro_num_seg - 1; rq->stats.lro_packets++; rq->stats.lro_bytes += cqe_bcnt; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 7c42be586be8..6cf6d93d8831 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -85,7 +85,7 @@ static struct mlx5_profile profile[] = { [2] = { .mask = MLX5_PROF_MASK_QP_SIZE | MLX5_PROF_MASK_MR_CACHE, - .log_max_qp = 18, + .log_max_qp = 17, .mr_cache[0] = { .size = 500, .limit = 250 @@ -153,9 +153,8 @@ static struct mlx5_profile profile[] = { }, }; -#define FW_INIT_TIMEOUT_MILI 2000 -#define FW_INIT_WAIT_MS 2 -#define FW_PRE_INIT_TIMEOUT_MILI 10000 +#define FW_INIT_TIMEOUT_MILI 2000 +#define FW_INIT_WAIT_MS 2 static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili) { @@ -433,13 +432,6 @@ static int handle_hca_cap(struct mlx5_core_dev *dev) MLX5_SET(cmd_hca_cap, set_hca_cap, pkey_table_size, to_fw_pkey_sz(128)); - /* Check log_max_qp from HCA caps to set in current profile */ - if (MLX5_CAP_GEN_MAX(dev, log_max_qp) < profile[prof_sel].log_max_qp) { - mlx5_core_warn(dev, "log_max_qp value in current profile is %d, changing it to HCA capability limit (%d)\n", - profile[prof_sel].log_max_qp, - MLX5_CAP_GEN_MAX(dev, log_max_qp)); - profile[prof_sel].log_max_qp = MLX5_CAP_GEN_MAX(dev, log_max_qp); - } if (prof->mask & MLX5_PROF_MASK_QP_SIZE) MLX5_SET(cmd_hca_cap, set_hca_cap, log_max_qp, prof->log_max_qp); @@ -513,20 +505,29 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i) struct mlx5_priv *priv = &mdev->priv; struct msix_entry *msix = priv->msix_arr; int irq = msix[i + MLX5_EQ_VEC_COMP_BASE].vector; + int numa_node = priv->numa_node; + int err; if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) { mlx5_core_warn(mdev, "zalloc_cpumask_var failed"); return -ENOMEM; } - cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node), + cpumask_set_cpu(cpumask_local_spread(i, numa_node), priv->irq_info[i].mask); - if (IS_ENABLED(CONFIG_SMP) && - irq_set_affinity_hint(irq, priv->irq_info[i].mask)) - mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x", irq); + err = irq_set_affinity_hint(irq, priv->irq_info[i].mask); + if (err) { + mlx5_core_warn(mdev, "irq_set_affinity_hint failed,irq 0x%.4x", + irq); + goto err_clear_mask; + } return 0; + +err_clear_mask: + free_cpumask_var(priv->irq_info[i].mask); + return err; } static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i) @@ -927,15 +928,6 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) */ dev->state = MLX5_DEVICE_STATE_UP; - /* wait for firmware to accept initialization segments configurations - */ - err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI); - if (err) { - dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n", - FW_PRE_INIT_TIMEOUT_MILI); - goto out; - } - err = mlx5_cmd_init(dev); if (err) { dev_err(&pdev->dev, "Failed initializing command interface, aborting\n"); diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.h b/drivers/net/ethernet/mellanox/mlxsw/pci.h index a0fbe00dd690..142f33d978c5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.h +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.h @@ -206,21 +206,21 @@ MLXSW_ITEM32(pci, eqe, owner, 0x0C, 0, 1); /* pci_eqe_cmd_token * Command completion event - token */ -MLXSW_ITEM32(pci, eqe, cmd_token, 0x00, 16, 16); +MLXSW_ITEM32(pci, eqe, cmd_token, 0x08, 16, 16); /* pci_eqe_cmd_status * Command completion event - status */ -MLXSW_ITEM32(pci, eqe, cmd_status, 0x00, 0, 8); +MLXSW_ITEM32(pci, eqe, cmd_status, 0x08, 0, 8); /* pci_eqe_cmd_out_param_h * Command completion event - output parameter - higher part */ -MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x04, 0, 32); +MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x0C, 0, 32); /* pci_eqe_cmd_out_param_l * Command completion event - output parameter - lower part */ -MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x08, 0, 32); +MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x10, 0, 32); #endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index c7fe61f1f89f..236fb5d2ad69 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -599,7 +599,7 @@ static inline void mlxsw_reg_spvid_pack(char *payload, u8 local_port, u16 pvid) #define MLXSW_REG_SPVM_ID 0x200F #define MLXSW_REG_SPVM_BASE_LEN 0x04 /* base length, without records */ #define MLXSW_REG_SPVM_REC_LEN 0x04 /* record length */ -#define MLXSW_REG_SPVM_REC_MAX_COUNT 255 +#define MLXSW_REG_SPVM_REC_MAX_COUNT 256 #define MLXSW_REG_SPVM_LEN (MLXSW_REG_SPVM_BASE_LEN + \ MLXSW_REG_SPVM_REC_LEN * MLXSW_REG_SPVM_REC_MAX_COUNT) @@ -1139,7 +1139,7 @@ static inline void mlxsw_reg_sfmr_pack(char *payload, #define MLXSW_REG_SPVMLR_ID 0x2020 #define MLXSW_REG_SPVMLR_BASE_LEN 0x04 /* base length, without records */ #define MLXSW_REG_SPVMLR_REC_LEN 0x04 /* record length */ -#define MLXSW_REG_SPVMLR_REC_MAX_COUNT 255 +#define MLXSW_REG_SPVMLR_REC_MAX_COUNT 256 #define MLXSW_REG_SPVMLR_LEN (MLXSW_REG_SPVMLR_BASE_LEN + \ MLXSW_REG_SPVMLR_REC_LEN * \ MLXSW_REG_SPVMLR_REC_MAX_COUNT) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index cb165c2d4803..3be4a2355ead 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -390,7 +390,6 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb, dev_kfree_skb_any(skb_orig); return NETDEV_TX_OK; } - dev_consume_skb_any(skb_orig); } if (eth_skb_pad(skb)) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index fb2d9a82ce3d..d85960cfb694 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -313,7 +313,6 @@ static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb, dev_kfree_skb_any(skb_orig); return NETDEV_TX_OK; } - dev_consume_skb_any(skb_orig); } mlxsw_sx_txhdr_construct(skb, &tx_info); len = skb->len; diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index 0798b4adb039..1bd419dbda6d 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -71,7 +71,7 @@ static int sonic_open(struct net_device *dev) for (i = 0; i < SONIC_NUM_RRS; i++) { dma_addr_t laddr = dma_map_single(lp->device, skb_put(lp->rx_skb[i], SONIC_RBSIZE), SONIC_RBSIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(lp->device, laddr)) { + if (!laddr) { while(i > 0) { /* free any that were mapped successfully */ i--; dma_unmap_single(lp->device, lp->rx_laddr[i], SONIC_RBSIZE, DMA_FROM_DEVICE); diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index e0993eba5df3..50d5604833ed 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -2223,6 +2223,8 @@ static irqreturn_t vxge_isr_napi(int irq, void *dev_id) return IRQ_NONE; } +#ifdef CONFIG_PCI_MSI + static irqreturn_t vxge_tx_msix_handle(int irq, void *dev_id) { struct vxge_fifo *fifo = (struct vxge_fifo *)dev_id; @@ -2440,13 +2442,16 @@ static void vxge_rem_msix_isr(struct vxgedev *vdev) if (vdev->config.intr_type == MSI_X) pci_disable_msix(vdev->pdev); } +#endif static void vxge_rem_isr(struct vxgedev *vdev) { - if (IS_ENABLED(CONFIG_PCI_MSI) && - vdev->config.intr_type == MSI_X) { +#ifdef CONFIG_PCI_MSI + if (vdev->config.intr_type == MSI_X) { vxge_rem_msix_isr(vdev); - } else if (vdev->config.intr_type == INTA) { + } else +#endif + if (vdev->config.intr_type == INTA) { synchronize_irq(vdev->pdev->irq); free_irq(vdev->pdev->irq, vdev); } @@ -2455,10 +2460,11 @@ static void vxge_rem_isr(struct vxgedev *vdev) static int vxge_add_isr(struct vxgedev *vdev) { int ret = 0; +#ifdef CONFIG_PCI_MSI int vp_idx = 0, intr_idx = 0, intr_cnt = 0, msix_idx = 0, irq_req = 0; int pci_fun = PCI_FUNC(vdev->pdev->devfn); - if (IS_ENABLED(CONFIG_PCI_MSI) && vdev->config.intr_type == MSI_X) + if (vdev->config.intr_type == MSI_X) ret = vxge_enable_msix(vdev); if (ret) { @@ -2469,7 +2475,7 @@ static int vxge_add_isr(struct vxgedev *vdev) vdev->config.intr_type = INTA; } - if (IS_ENABLED(CONFIG_PCI_MSI) && vdev->config.intr_type == MSI_X) { + if (vdev->config.intr_type == MSI_X) { for (intr_idx = 0; intr_idx < (vdev->no_of_vpath * VXGE_HW_VPATH_MSIX_ACTIVE); intr_idx++) { @@ -2570,8 +2576,9 @@ static int vxge_add_isr(struct vxgedev *vdev) vdev->vxge_entries[intr_cnt].in_use = 1; vdev->vxge_entries[intr_cnt].arg = &vdev->vpaths[0]; } - INTA_MODE: +#endif + if (vdev->config.intr_type == INTA) { snprintf(vdev->desc[0], VXGE_INTR_STRLEN, "%s:vxge:INTA", vdev->ndev->name); @@ -3882,12 +3889,12 @@ static void vxge_device_config_init(struct vxge_hw_device_config *device_config, if (max_mac_vpath > VXGE_MAX_MAC_ADDR_COUNT) max_mac_vpath = VXGE_MAX_MAC_ADDR_COUNT; - if (!IS_ENABLED(CONFIG_PCI_MSI)) { - vxge_debug_init(VXGE_ERR, - "%s: This Kernel does not support " - "MSI-X. Defaulting to INTA", VXGE_DRIVER_NAME); - *intr_type = INTA; - } +#ifndef CONFIG_PCI_MSI + vxge_debug_init(VXGE_ERR, + "%s: This Kernel does not support " + "MSI-X. Defaulting to INTA", VXGE_DRIVER_NAME); + *intr_type = INTA; +#endif /* Configure whether MSI-X or IRQL. */ switch (*intr_type) { diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c index e30676515529..b8d5270359cd 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c @@ -247,7 +247,7 @@ nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) cmd.req.arg3 = 0; if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE) - rcode = netxen_issue_cmd(adapter, &cmd); + netxen_issue_cmd(adapter, &cmd); if (rcode != NX_RCODE_SUCCESS) return -EIO; diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c index 21e0af2620ee..7ccdb46c6764 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c @@ -43,7 +43,7 @@ #define ILT_CFG_REG(cli, reg) PSWRQ2_REG_ ## cli ## _ ## reg ## _RT_OFFSET /* ILT entry structure */ -#define ILT_ENTRY_PHY_ADDR_MASK (~0ULL >> 12) +#define ILT_ENTRY_PHY_ADDR_MASK 0x000FFFFFFFFFFFULL #define ILT_ENTRY_PHY_ADDR_SHIFT 0 #define ILT_ENTRY_VALID_MASK 0x1ULL #define ILT_ENTRY_VALID_SHIFT 52 diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 35e1468d8196..174f7341c5c3 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -22,7 +22,6 @@ #include #include #include -#include #include "qed.h" #include "qed_sp.h" @@ -461,16 +460,8 @@ static irqreturn_t qed_single_int(int irq, void *dev_instance) /* Fastpath interrupts */ for (j = 0; j < 64; j++) { if ((0x2ULL << j) & status) { - struct qed_simd_fp_handler *p_handler = - &hwfn->simd_proto_handler[j]; - - if (p_handler->func) - p_handler->func(p_handler->token); - else - DP_NOTICE(hwfn, - "Not calling fastpath handler as it is NULL [handler #%d, status 0x%llx]\n", - j, status); - + hwfn->simd_proto_handler[j].func( + hwfn->simd_proto_handler[j].token); status &= ~(0x2ULL << j); rc = IRQ_HANDLED; } @@ -643,14 +634,6 @@ static int qed_slowpath_setup_int(struct qed_dev *cdev, /* We want a minimum of one slowpath and one fastpath vector per hwfn */ cdev->int_params.in.min_msix_cnt = cdev->num_hwfns * 2; - if (is_kdump_kernel()) { - DP_INFO(cdev, - "Kdump kernel: Limit the max number of requested MSI-X vectors to %hd\n", - cdev->int_params.in.min_msix_cnt); - cdev->int_params.in.num_vectors = - cdev->int_params.in.min_msix_cnt; - } - rc = qed_set_int_mode(cdev, false); if (rc) { DP_ERR(cdev, "qed_slowpath_setup_int ERR\n"); diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index c898006abb32..20d048cdcb88 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -420,7 +420,6 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn, break; default: p_link->speed = 0; - p_link->link_up = 0; } /* Correct speed according to bandwidth allocation */ diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c index 40365cb1abe6..3dd548ab8df1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c @@ -794,12 +794,13 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn, * in a bitmap and increasing the chain consumer only * for the first successive completed entries. */ - __set_bit(pos, p_spq->p_comp_bitmap); + bitmap_set(p_spq->p_comp_bitmap, pos, SPQ_RING_SIZE); while (test_bit(p_spq->comp_bitmap_idx, p_spq->p_comp_bitmap)) { - __clear_bit(p_spq->comp_bitmap_idx, - p_spq->p_comp_bitmap); + bitmap_clear(p_spq->p_comp_bitmap, + p_spq->comp_bitmap_idx, + SPQ_RING_SIZE); p_spq->comp_bitmap_idx++; qed_chain_return_produced(&p_spq->chain); } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index b4f3cb55605e..f9640d5ce6ba 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -3850,7 +3850,7 @@ static void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) struct list_head *head = &mbx->cmd_q; struct qlcnic_cmd_args *cmd = NULL; - spin_lock_bh(&mbx->queue_lock); + spin_lock(&mbx->queue_lock); while (!list_empty(head)) { cmd = list_entry(head->next, struct qlcnic_cmd_args, list); @@ -3861,7 +3861,7 @@ static void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) qlcnic_83xx_notify_cmd_completion(adapter, cmd); } - spin_unlock_bh(&mbx->queue_lock); + spin_unlock(&mbx->queue_lock); } static int qlcnic_83xx_check_mbx_status(struct qlcnic_adapter *adapter) @@ -3897,12 +3897,12 @@ static void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter, { struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; - spin_lock_bh(&mbx->queue_lock); + spin_lock(&mbx->queue_lock); list_del(&cmd->list); mbx->num_cmds--; - spin_unlock_bh(&mbx->queue_lock); + spin_unlock(&mbx->queue_lock); qlcnic_83xx_notify_cmd_completion(adapter, cmd); } @@ -3967,7 +3967,7 @@ static int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, init_completion(&cmd->completion); cmd->rsp_opcode = QLC_83XX_MBX_RESPONSE_UNKNOWN; - spin_lock_bh(&mbx->queue_lock); + spin_lock(&mbx->queue_lock); list_add_tail(&cmd->list, &mbx->cmd_q); mbx->num_cmds++; @@ -3975,7 +3975,7 @@ static int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, *timeout = cmd->total_cmds * QLC_83XX_MBX_TIMEOUT; queue_work(mbx->work_q, &mbx->work); - spin_unlock_bh(&mbx->queue_lock); + spin_unlock(&mbx->queue_lock); return 0; } @@ -4071,15 +4071,15 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work) mbx->rsp_status = QLC_83XX_MBX_RESPONSE_WAIT; spin_unlock_irqrestore(&mbx->aen_lock, flags); - spin_lock_bh(&mbx->queue_lock); + spin_lock(&mbx->queue_lock); if (list_empty(head)) { - spin_unlock_bh(&mbx->queue_lock); + spin_unlock(&mbx->queue_lock); return; } cmd = list_entry(head->next, struct qlcnic_cmd_args, list); - spin_unlock_bh(&mbx->queue_lock); + spin_unlock(&mbx->queue_lock); mbx_ops->encode_cmd(adapter, cmd); mbx_ops->nofity_fw(adapter, QLC_83XX_MBX_REQUEST); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index bd1ec70fb736..509b596cf1e8 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c @@ -341,7 +341,7 @@ qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg) } return -EIO; } - udelay(1200); + usleep_range(1000, 1500); } if (id_reg) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index ffa6885acfc8..7327b729ba2e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -127,8 +127,6 @@ static int qlcnic_sriov_virtid_fn(struct qlcnic_adapter *adapter, int vf_id) return 0; pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); - if (!pos) - return 0; pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset); pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index b53a18e365c2..ccbb04503b27 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c @@ -1128,8 +1128,6 @@ static ssize_t qlcnic_83xx_sysfs_flash_write_handler(struct file *filp, struct qlcnic_adapter *adapter = dev_get_drvdata(dev); ret = kstrtoul(buf, 16, &data); - if (ret) - return ret; switch (data) { case QLC_83XX_FLASH_SECTOR_ERASE_CMD: diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c index e3223f2fe2ff..829be21f97b2 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c @@ -724,7 +724,7 @@ static void ql_build_coredump_seg_header( seg_hdr->cookie = MPI_COREDUMP_COOKIE; seg_hdr->segNum = seg_number; seg_hdr->segSize = seg_size; - strncpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1); + memcpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1); } /* @@ -765,7 +765,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) sizeof(struct mpi_coredump_global_header); mpi_coredump->mpi_global_header.imageSize = sizeof(struct ql_mpi_coredump); - strncpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump", + memcpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump", sizeof(mpi_coredump->mpi_global_header.idString)); /* Get generic NIC reg dump */ @@ -1255,7 +1255,7 @@ static void ql_gen_reg_dump(struct ql_adapter *qdev, sizeof(struct mpi_coredump_global_header); mpi_coredump->mpi_global_header.imageSize = sizeof(struct ql_reg_dump); - strncpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump", + memcpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump", sizeof(mpi_coredump->mpi_global_header.idString)); diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 7886a8a5b55b..1ef03939d25f 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -296,9 +296,8 @@ qcaspi_receive(struct qcaspi *qca) /* Allocate rx SKB if we don't have one available. */ if (!qca->rx_skb) { - qca->rx_skb = netdev_alloc_skb_ip_align(net_dev, - net_dev->mtu + - VLAN_ETH_HLEN); + qca->rx_skb = netdev_alloc_skb(net_dev, + net_dev->mtu + VLAN_ETH_HLEN); if (!qca->rx_skb) { netdev_dbg(net_dev, "out of RX resources\n"); qca->stats.out_of_mem++; @@ -378,7 +377,7 @@ qcaspi_receive(struct qcaspi *qca) qca->rx_skb, qca->rx_skb->dev); qca->rx_skb->ip_summed = CHECKSUM_UNNECESSARY; netif_rx_ni(qca->rx_skb); - qca->rx_skb = netdev_alloc_skb_ip_align(net_dev, + qca->rx_skb = netdev_alloc_skb(net_dev, net_dev->mtu + VLAN_ETH_HLEN); if (!qca->rx_skb) { netdev_dbg(net_dev, "out of RX resources\n"); @@ -635,7 +634,7 @@ qcaspi_netdev_open(struct net_device *dev) return ret; } - /* SPI thread takes care of TX queue */ + netif_start_queue(qca->net_dev); return 0; } @@ -739,9 +738,6 @@ qcaspi_netdev_tx_timeout(struct net_device *dev) qca->net_dev->stats.tx_errors++; /* Trigger tx queue flush and QCA7000 reset */ qca->sync = QCASPI_SYNC_UNKNOWN; - - if (qca->spi_thread) - wake_up_process(qca->spi_thread); } static int @@ -763,8 +759,7 @@ qcaspi_netdev_init(struct net_device *dev) if (!qca->rx_buffer) return -ENOBUFS; - qca->rx_skb = netdev_alloc_skb_ip_align(dev, qca->net_dev->mtu + - VLAN_ETH_HLEN); + qca->rx_skb = netdev_alloc_skb(dev, qca->net_dev->mtu + VLAN_ETH_HLEN); if (!qca->rx_skb) { kfree(qca->rx_buffer); netdev_info(qca->net_dev, "Failed to allocate RX sk_buff.\n"); @@ -868,22 +863,22 @@ qca_spi_probe(struct spi_device *spi) if ((qcaspi_clkspeed < QCASPI_CLK_SPEED_MIN) || (qcaspi_clkspeed > QCASPI_CLK_SPEED_MAX)) { - dev_err(&spi->dev, "Invalid clkspeed: %d\n", - qcaspi_clkspeed); + dev_info(&spi->dev, "Invalid clkspeed: %d\n", + qcaspi_clkspeed); return -EINVAL; } if ((qcaspi_burst_len < QCASPI_BURST_LEN_MIN) || (qcaspi_burst_len > QCASPI_BURST_LEN_MAX)) { - dev_err(&spi->dev, "Invalid burst len: %d\n", - qcaspi_burst_len); + dev_info(&spi->dev, "Invalid burst len: %d\n", + qcaspi_burst_len); return -EINVAL; } if ((qcaspi_pluggable < QCASPI_PLUGGABLE_MIN) || (qcaspi_pluggable > QCASPI_PLUGGABLE_MAX)) { - dev_err(&spi->dev, "Invalid pluggable: %d\n", - qcaspi_pluggable); + dev_info(&spi->dev, "Invalid pluggable: %d\n", + qcaspi_pluggable); return -EINVAL; } @@ -944,8 +939,8 @@ qca_spi_probe(struct spi_device *spi) } if (register_netdev(qcaspi_devs)) { - dev_err(&spi->dev, "Unable to register net device %s\n", - qcaspi_devs->name); + dev_info(&spi->dev, "Unable to register net device %s\n", + qcaspi_devs->name); free_netdev(qcaspi_devs); return -EFAULT; } diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c index d987d571fdd6..ef668d300800 100644 --- a/drivers/net/ethernet/realtek/8139too.c +++ b/drivers/net/ethernet/realtek/8139too.c @@ -2229,7 +2229,7 @@ static void rtl8139_poll_controller(struct net_device *dev) struct rtl8139_private *tp = netdev_priv(dev); const int irq = tp->pci_dev->irq; - disable_irq_nosync(irq); + disable_irq(irq); rtl8139_interrupt(irq, dev); enable_irq(irq); } diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 8b4069ea52ce..79ef799f88ab 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -326,7 +326,6 @@ enum cfg_version { static const struct pci_device_id rtl8169_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161), 0, 0, RTL_CFG_1 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, @@ -1387,7 +1386,7 @@ DECLARE_RTL_COND(rtl_ocp_tx_cond) { void __iomem *ioaddr = tp->mmio_addr; - return RTL_R8(IBISR0) & 0x20; + return RTL_R8(IBISR0) & 0x02; } static void rtl8168ep_stop_cmac(struct rtl8169_private *tp) @@ -1395,7 +1394,7 @@ static void rtl8168ep_stop_cmac(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; RTL_W8(IBCR2, RTL_R8(IBCR2) & ~0x01); - rtl_msleep_loop_wait_high(tp, &rtl_ocp_tx_cond, 50, 2000); + rtl_msleep_loop_wait_low(tp, &rtl_ocp_tx_cond, 50, 2000); RTL_W8(IBISR0, RTL_R8(IBISR0) | 0x20); RTL_W8(IBCR0, RTL_R8(IBCR0) & ~0x01); } @@ -2205,14 +2204,19 @@ static bool rtl8169_do_counters(struct net_device *dev, u32 counter_cmd) void __iomem *ioaddr = tp->mmio_addr; dma_addr_t paddr = tp->counters_phys_addr; u32 cmd; + bool ret; RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - RTL_R32(CounterAddrHigh); cmd = (u64)paddr & DMA_BIT_MASK(32); RTL_W32(CounterAddrLow, cmd); RTL_W32(CounterAddrLow, cmd | counter_cmd); - return rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000); + ret = rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000); + + RTL_W32(CounterAddrLow, 0); + RTL_W32(CounterAddrHigh, 0); + + return ret; } static bool rtl8169_reset_counters(struct net_device *dev) @@ -4832,9 +4836,6 @@ static void rtl_pll_power_down(struct rtl8169_private *tp) static void rtl_pll_power_up(struct rtl8169_private *tp) { rtl_generic_op(tp, tp->pll_power_ops.up); - - /* give MAC/PHY some time to resume */ - msleep(20); } static void rtl_init_pll_power_ops(struct rtl8169_private *tp) @@ -8414,12 +8415,12 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_msi_4; } - pci_set_drvdata(pdev, dev); - rc = register_netdev(dev); if (rc < 0) goto err_out_cnt_5; + pci_set_drvdata(pdev, dev); + netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n", rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr, (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq); diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index f735dfcb64ae..467d41698fd5 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -171,49 +171,6 @@ static struct mdiobb_ops bb_ops = { .get_mdio_data = ravb_get_mdio_data, }; -/* Free TX skb function for AVB-IP */ -static int ravb_tx_free(struct net_device *ndev, int q, bool free_txed_only) -{ - struct ravb_private *priv = netdev_priv(ndev); - struct net_device_stats *stats = &priv->stats[q]; - struct ravb_tx_desc *desc; - int free_num = 0; - int entry; - u32 size; - - for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) { - bool txed; - - entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] * - NUM_TX_DESC); - desc = &priv->tx_ring[q][entry]; - txed = desc->die_dt == DT_FEMPTY; - if (free_txed_only && !txed) - break; - /* Descriptor type must be checked before all other reads */ - dma_rmb(); - size = le16_to_cpu(desc->ds_tagl) & TX_DS; - /* Free the original skb. */ - if (priv->tx_skb[q][entry / NUM_TX_DESC]) { - dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr), - size, DMA_TO_DEVICE); - /* Last packet descriptor? */ - if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) { - entry /= NUM_TX_DESC; - dev_kfree_skb_any(priv->tx_skb[q][entry]); - priv->tx_skb[q][entry] = NULL; - if (txed) - stats->tx_packets++; - } - free_num++; - } - if (txed) - stats->tx_bytes += size; - desc->die_dt = DT_EEMPTY; - } - return free_num; -} - /* Free skb's and DMA buffers for Ethernet AVB */ static void ravb_ring_free(struct net_device *ndev, int q) { @@ -221,17 +178,27 @@ static void ravb_ring_free(struct net_device *ndev, int q) int ring_size; int i; + /* Free RX skb ringbuffer */ + if (priv->rx_skb[q]) { + for (i = 0; i < priv->num_rx_ring[q]; i++) + dev_kfree_skb(priv->rx_skb[q][i]); + } + kfree(priv->rx_skb[q]); + priv->rx_skb[q] = NULL; + + /* Free TX skb ringbuffer */ + if (priv->tx_skb[q]) { + for (i = 0; i < priv->num_tx_ring[q]; i++) + dev_kfree_skb(priv->tx_skb[q][i]); + } + kfree(priv->tx_skb[q]); + priv->tx_skb[q] = NULL; + + /* Free aligned TX buffers */ + kfree(priv->tx_align[q]); + priv->tx_align[q] = NULL; + if (priv->rx_ring[q]) { - for (i = 0; i < priv->num_rx_ring[q]; i++) { - struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i]; - - if (!dma_mapping_error(ndev->dev.parent, - le32_to_cpu(desc->dptr))) - dma_unmap_single(ndev->dev.parent, - le32_to_cpu(desc->dptr), - PKT_BUF_SZ, - DMA_FROM_DEVICE); - } ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1); dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q], @@ -240,32 +207,12 @@ static void ravb_ring_free(struct net_device *ndev, int q) } if (priv->tx_ring[q]) { - ravb_tx_free(ndev, q, false); - ring_size = sizeof(struct ravb_tx_desc) * (priv->num_tx_ring[q] * NUM_TX_DESC + 1); dma_free_coherent(ndev->dev.parent, ring_size, priv->tx_ring[q], priv->tx_desc_dma[q]); priv->tx_ring[q] = NULL; } - - /* Free RX skb ringbuffer */ - if (priv->rx_skb[q]) { - for (i = 0; i < priv->num_rx_ring[q]; i++) - dev_kfree_skb(priv->rx_skb[q][i]); - } - kfree(priv->rx_skb[q]); - priv->rx_skb[q] = NULL; - - /* Free aligned TX buffers */ - kfree(priv->tx_align[q]); - priv->tx_align[q] = NULL; - - /* Free TX skb ringbuffer. - * SKBs are freed by ravb_tx_free() call above. - */ - kfree(priv->tx_skb[q]); - priv->tx_skb[q] = NULL; } /* Format skb and descriptor buffer for Ethernet AVB */ @@ -473,6 +420,44 @@ static int ravb_dmac_init(struct net_device *ndev) return 0; } +/* Free TX skb function for AVB-IP */ +static int ravb_tx_free(struct net_device *ndev, int q) +{ + struct ravb_private *priv = netdev_priv(ndev); + struct net_device_stats *stats = &priv->stats[q]; + struct ravb_tx_desc *desc; + int free_num = 0; + int entry; + u32 size; + + for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) { + entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] * + NUM_TX_DESC); + desc = &priv->tx_ring[q][entry]; + if (desc->die_dt != DT_FEMPTY) + break; + /* Descriptor type must be checked before all other reads */ + dma_rmb(); + size = le16_to_cpu(desc->ds_tagl) & TX_DS; + /* Free the original skb. */ + if (priv->tx_skb[q][entry / NUM_TX_DESC]) { + dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr), + size, DMA_TO_DEVICE); + /* Last packet descriptor? */ + if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) { + entry /= NUM_TX_DESC; + dev_kfree_skb_any(priv->tx_skb[q][entry]); + priv->tx_skb[q][entry] = NULL; + stats->tx_packets++; + } + free_num++; + } + stats->tx_bytes += size; + desc->die_dt = DT_EEMPTY; + } + return free_num; +} + static void ravb_get_tx_tstamp(struct net_device *ndev) { struct ravb_private *priv = netdev_priv(ndev); @@ -812,7 +797,7 @@ static int ravb_poll(struct napi_struct *napi, int budget) spin_lock_irqsave(&priv->lock, flags); /* Clear TX interrupt */ ravb_write(ndev, ~mask, TIS); - ravb_tx_free(ndev, q, true); + ravb_tx_free(ndev, q); netif_wake_subqueue(ndev, q); mmiowb(); spin_unlock_irqrestore(&priv->lock, flags); @@ -831,10 +816,14 @@ static int ravb_poll(struct napi_struct *napi, int budget) /* Receive error message handling */ priv->rx_over_errors = priv->stats[RAVB_BE].rx_over_errors; priv->rx_over_errors += priv->stats[RAVB_NC].rx_over_errors; - if (priv->rx_over_errors != ndev->stats.rx_over_errors) + if (priv->rx_over_errors != ndev->stats.rx_over_errors) { ndev->stats.rx_over_errors = priv->rx_over_errors; - if (priv->rx_fifo_errors != ndev->stats.rx_fifo_errors) + netif_err(priv, rx_err, ndev, "Receive Descriptor Empty\n"); + } + if (priv->rx_fifo_errors != ndev->stats.rx_fifo_errors) { ndev->stats.rx_fifo_errors = priv->rx_fifo_errors; + netif_err(priv, rx_err, ndev, "Receive FIFO Overflow\n"); + } out: return budget - quota; } @@ -1341,19 +1330,6 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) buffer = PTR_ALIGN(priv->tx_align[q], DPTR_ALIGN) + entry / NUM_TX_DESC * DPTR_ALIGN; len = PTR_ALIGN(skb->data, DPTR_ALIGN) - skb->data; - /* Zero length DMA descriptors are problematic as they seem to - * terminate DMA transfers. Avoid them by simply using a length of - * DPTR_ALIGN (4) when skb data is aligned to DPTR_ALIGN. - * - * As skb is guaranteed to have at least ETH_ZLEN (60) bytes of - * data by the call to skb_put_padto() above this is safe with - * respect to both the length of the first DMA descriptor (len) - * overflowing the available data and the length of the second DMA - * descriptor (skb->len - len) being negative. - */ - if (len == 0) - len = DPTR_ALIGN; - memcpy(buffer, skb->data, len); dma_addr = dma_map_single(ndev->dev.parent, buffer, len, DMA_TO_DEVICE); if (dma_mapping_error(ndev->dev.parent, dma_addr)) @@ -1404,8 +1380,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) priv->cur_tx[q] += NUM_TX_DESC; if (priv->cur_tx[q] - priv->dirty_tx[q] > - (priv->num_tx_ring[q] - 1) * NUM_TX_DESC && - !ravb_tx_free(ndev, q, true)) + (priv->num_tx_ring[q] - 1) * NUM_TX_DESC && !ravb_tx_free(ndev, q)) netif_stop_subqueue(ndev, q); exit: diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index afaf79b8761f..36fc9427418f 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -750,7 +750,6 @@ static struct sh_eth_cpu_data sh7734_data = { .tsu = 1, .hw_crc = 1, .select_mii = 1, - .shift_rd0 = 1, }; /* SH7763 */ @@ -819,7 +818,6 @@ static struct sh_eth_cpu_data r8a7740_data = { .rpadir_value = 2 << 16, .no_trimd = 1, .no_ade = 1, - .hw_crc = 1, .tsu = 1, .select_mii = 1, .shift_rd0 = 1, @@ -834,7 +832,7 @@ static struct sh_eth_cpu_data r7s72100_data = { .ecsr_value = ECSR_ICD, .ecsipr_value = ECSIPR_ICDIP, - .eesipr_value = 0xe77f009f, + .eesipr_value = 0xff7f009f, .tx_check = EESR_TC1 | EESR_FTC, .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | @@ -3176,37 +3174,18 @@ static int sh_eth_drv_probe(struct platform_device *pdev) /* ioremap the TSU registers */ if (mdp->cd->tsu) { struct resource *rtsu; - rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!rtsu) { - dev_err(&pdev->dev, "no TSU resource\n"); - ret = -ENODEV; - goto out_release; - } - /* We can only request the TSU region for the first port - * of the two sharing this TSU for the probe to succeed... - */ - if (devno % 2 == 0 && - !devm_request_mem_region(&pdev->dev, rtsu->start, - resource_size(rtsu), - dev_name(&pdev->dev))) { - dev_err(&pdev->dev, "can't request TSU resource.\n"); - ret = -EBUSY; - goto out_release; - } - mdp->tsu_addr = devm_ioremap(&pdev->dev, rtsu->start, - resource_size(rtsu)); - if (!mdp->tsu_addr) { - dev_err(&pdev->dev, "TSU region ioremap() failed.\n"); - ret = -ENOMEM; + mdp->tsu_addr = devm_ioremap_resource(&pdev->dev, rtsu); + if (IS_ERR(mdp->tsu_addr)) { + ret = PTR_ERR(mdp->tsu_addr); goto out_release; } mdp->port = devno % 2; ndev->features = NETIF_F_HW_VLAN_CTAG_FILTER; } - /* Need to init only the first port of the two sharing a TSU */ - if (devno % 2 == 0) { + /* initialize first or needed device */ + if (!devno || pd->needs_init) { if (mdp->cd->chip_reset) mdp->cd->chip_reset(ndev); @@ -3222,7 +3201,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev) /* MDIO bus init */ ret = sh_mdio_init(mdp, pd); if (ret) { - dev_err(&pdev->dev, "failed to initialise MDIO\n"); + dev_err(&ndev->dev, "failed to initialise MDIO\n"); goto out_release; } diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 0d18be0fed8e..72fcfc924589 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -339,7 +339,7 @@ enum FELIC_MODE_BIT { ECMR_DPAD = 0x00200000, ECMR_RZPF = 0x00100000, ECMR_ZPF = 0x00080000, ECMR_PFR = 0x00040000, ECMR_RXF = 0x00020000, ECMR_TXF = 0x00010000, ECMR_MCT = 0x00002000, ECMR_PRCEF = 0x00001000, - ECMR_MPDE = 0x00000200, ECMR_RE = 0x00000040, ECMR_TE = 0x00000020, + ECMR_PMDE = 0x00000200, ECMR_RE = 0x00000040, ECMR_TE = 0x00000020, ECMR_RTM = 0x00000010, ECMR_ILB = 0x00000008, ECMR_ELB = 0x00000004, ECMR_DM = 0x00000002, ECMR_PRM = 0x00000001, }; diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 3920c3eb6006..2b34622a4bfe 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4475,7 +4475,7 @@ static int rocker_port_obj_add(struct net_device *dev, fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj); err = rocker_port_fib_ipv4(rocker_port, trans, htonl(fib4->dst), fib4->dst_len, - fib4->fi, fib4->tb_id, 0); + &fib4->fi, fib4->tb_id, 0); break; case SWITCHDEV_OBJ_ID_PORT_FDB: err = rocker_port_fdb_add(rocker_port, trans, @@ -4547,7 +4547,7 @@ static int rocker_port_obj_del(struct net_device *dev, fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj); err = rocker_port_fib_ipv4(rocker_port, NULL, htonl(fib4->dst), fib4->dst_len, - fib4->fi, fib4->tb_id, + &fib4->fi, fib4->tb_id, ROCKER_OP_FLAG_REMOVE); break; case SWITCHDEV_OBJ_ID_PORT_FDB: diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 063aca17e698..e6a084a6be12 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -619,17 +619,6 @@ static int efx_ef10_link_piobufs(struct efx_nic *efx) return rc; } -static void efx_ef10_forget_old_piobufs(struct efx_nic *efx) -{ - struct efx_channel *channel; - struct efx_tx_queue *tx_queue; - - /* All our existing PIO buffers went away */ - efx_for_each_channel(channel, efx) - efx_for_each_channel_tx_queue(tx_queue, channel) - tx_queue->piobuf = NULL; -} - #else /* !EFX_USE_PIO */ static int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n) @@ -646,10 +635,6 @@ static void efx_ef10_free_piobufs(struct efx_nic *efx) { } -static void efx_ef10_forget_old_piobufs(struct efx_nic *efx) -{ -} - #endif /* EFX_USE_PIO */ static void efx_ef10_remove(struct efx_nic *efx) @@ -1033,7 +1018,6 @@ static void efx_ef10_reset_mc_allocations(struct efx_nic *efx) nic_data->must_realloc_vis = true; nic_data->must_restore_filters = true; nic_data->must_restore_piobufs = true; - efx_ef10_forget_old_piobufs(efx); nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID; /* Driver-created vswitches and vports must be re-created */ @@ -4307,7 +4291,7 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx) * MCFW do not support VFs. */ rc = efx_ef10_vport_set_mac_address(efx); - } else if (rc) { + } else { efx_mcdi_display_error(efx, MC_CMD_VADAPTOR_SET_MAC, sizeof(inbuf), NULL, 0, rc); } diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 8e832ba8ab24..d790cb8d9db3 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -2796,11 +2796,6 @@ const struct efx_nic_type falcon_a1_nic_type = { .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, .offload_features = NETIF_F_IP_CSUM, .mcdi_max_ver = -1, -#ifdef CONFIG_SFC_SRIOV - .vswitching_probe = efx_port_dummy_op_int, - .vswitching_restore = efx_port_dummy_op_int, - .vswitching_remove = efx_port_dummy_op_void, -#endif }; const struct efx_nic_type falcon_b0_nic_type = { @@ -2902,9 +2897,4 @@ const struct efx_nic_type falcon_b0_nic_type = { .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, .mcdi_max_ver = -1, .max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS, -#ifdef CONFIG_SFC_SRIOV - .vswitching_probe = efx_port_dummy_op_int, - .vswitching_restore = efx_port_dummy_op_int, - .vswitching_remove = efx_port_dummy_op_void, -#endif }; diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 23a038810083..0e2fc1a844ab 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -540,7 +540,7 @@ static inline void smc_rcv(struct net_device *dev) #define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags) #define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags) #else -#define smc_special_trylock(lock, flags) ((void)flags, true) +#define smc_special_trylock(lock, flags) (flags == flags) #define smc_special_lock(lock, flags) do { flags = 0; } while (0) #define smc_special_unlock(lock, flags) do { flags = 0; } while (0) #endif @@ -2269,13 +2269,6 @@ static int smc_drv_probe(struct platform_device *pdev) if (pd) { memcpy(&lp->cfg, pd, sizeof(lp->cfg)); lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags); - - if (!SMC_8BIT(lp) && !SMC_16BIT(lp)) { - dev_err(&pdev->dev, - "at least one of 8-bit or 16-bit access support is required.\n"); - ret = -ENXIO; - goto out_free_netdev; - } } #if IS_BUILTIN(CONFIG_OF) diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index 29df0465daf4..a3c129e1e40a 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -36,27 +36,6 @@ #include #include -/* - * Any 16-bit access is performed with two 8-bit accesses if the hardware - * can't do it directly. Most registers are 16-bit so those are mandatory. - */ -#define SMC_outw_b(x, a, r) \ - do { \ - unsigned int __val16 = (x); \ - unsigned int __reg = (r); \ - SMC_outb(__val16, a, __reg); \ - SMC_outb(__val16 >> 8, a, __reg + (1 << SMC_IO_SHIFT)); \ - } while (0) - -#define SMC_inw_b(a, r) \ - ({ \ - unsigned int __val16; \ - unsigned int __reg = r; \ - __val16 = SMC_inb(a, __reg); \ - __val16 |= SMC_inb(a, __reg + (1 << SMC_IO_SHIFT)) << 8; \ - __val16; \ - }) - /* * Define your architecture specific bus configuration parameters here. */ @@ -76,30 +55,10 @@ #define SMC_IO_SHIFT (lp->io_shift) #define SMC_inb(a, r) readb((a) + (r)) -#define SMC_inw(a, r) \ - ({ \ - unsigned int __smc_r = r; \ - SMC_16BIT(lp) ? readw((a) + __smc_r) : \ - SMC_8BIT(lp) ? SMC_inw_b(a, __smc_r) : \ - ({ BUG(); 0; }); \ - }) - +#define SMC_inw(a, r) readw((a) + (r)) #define SMC_inl(a, r) readl((a) + (r)) #define SMC_outb(v, a, r) writeb(v, (a) + (r)) -#define SMC_outw(v, a, r) \ - do { \ - unsigned int __v = v, __smc_r = r; \ - if (SMC_16BIT(lp)) \ - __SMC_outw(__v, a, __smc_r); \ - else if (SMC_8BIT(lp)) \ - SMC_outw_b(__v, a, __smc_r); \ - else \ - BUG(); \ - } while (0) - #define SMC_outl(v, a, r) writel(v, (a) + (r)) -#define SMC_insb(a, r, p, l) readsb((a) + (r), p, l) -#define SMC_outsb(a, r, p, l) writesb((a) + (r), p, l) #define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) #define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) @@ -107,7 +66,7 @@ #define SMC_IRQ_FLAGS (-1) /* from resource */ /* We actually can't write halfwords properly if not word aligned */ -static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg) +static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg) { if ((machine_is_mainstone() || machine_is_stargate2() || machine_is_pxa_idp()) && reg & 2) { @@ -446,8 +405,24 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma, #if ! SMC_CAN_USE_16BIT -#define SMC_outw(x, ioaddr, reg) SMC_outw_b(x, ioaddr, reg) -#define SMC_inw(ioaddr, reg) SMC_inw_b(ioaddr, reg) +/* + * Any 16-bit access is performed with two 8-bit accesses if the hardware + * can't do it directly. Most registers are 16-bit so those are mandatory. + */ +#define SMC_outw(x, ioaddr, reg) \ + do { \ + unsigned int __val16 = (x); \ + SMC_outb( __val16, ioaddr, reg ); \ + SMC_outb( __val16 >> 8, ioaddr, reg + (1 << SMC_IO_SHIFT));\ + } while (0) +#define SMC_inw(ioaddr, reg) \ + ({ \ + unsigned int __val16; \ + __val16 = SMC_inb( ioaddr, reg ); \ + __val16 |= SMC_inb( ioaddr, reg + (1 << SMC_IO_SHIFT)) << 8; \ + __val16; \ + }) + #define SMC_insw(a, r, p, l) BUG() #define SMC_outsw(a, r, p, l) BUG() diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 7bba30f24135..a5b869eb4678 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -54,7 +54,7 @@ #include #include -#define STMMAC_ALIGN(x) __ALIGN_KERNEL(x, SMP_CACHE_BYTES) +#define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x) /* Module parameters */ #define TX_TIMEO 5000 @@ -272,14 +272,8 @@ bool stmmac_eee_init(struct stmmac_priv *priv) { char *phy_bus_name = priv->plat->phy_bus_name; unsigned long flags; - int interface = priv->plat->interface; bool ret = false; - if ((interface != PHY_INTERFACE_MODE_MII) && - (interface != PHY_INTERFACE_MODE_GMII) && - !phy_interface_mode_is_rgmii(interface)) - goto out; - /* Using PCS we cannot dial with the phy registers at this stage * so we do not support extra feature like EEE. */ @@ -2945,6 +2939,12 @@ int stmmac_dvr_probe(struct device *device, spin_lock_init(&priv->lock); spin_lock_init(&priv->tx_lock); + ret = register_netdev(ndev); + if (ret) { + pr_err("%s: ERROR %i registering the device\n", __func__, ret); + goto error_netdev_register; + } + /* If a specific clk_csr value is passed from the platform * this means that the CSR Clock Range selection cannot be * changed at run-time and it is fixed. Viceversa the driver'll try to @@ -2969,21 +2969,11 @@ int stmmac_dvr_probe(struct device *device, } } - ret = register_netdev(ndev); - if (ret) { - netdev_err(priv->dev, "%s: ERROR %i registering the device\n", - __func__, ret); - goto error_netdev_register; - } - - return ret; + return 0; -error_netdev_register: - if (priv->pcs != STMMAC_PCS_RGMII && - priv->pcs != STMMAC_PCS_TBI && - priv->pcs != STMMAC_PCS_RTBI) - stmmac_mdio_unregister(ndev); error_mdio_register: + unregister_netdev(ndev); +error_netdev_register: netif_napi_del(&priv->napi); error_hw_init: clk_disable_unprepare(priv->pclk); diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index ccebf89aa1e4..ab6051a43134 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -3442,7 +3442,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np, len = (val & RCR_ENTRY_L2_LEN) >> RCR_ENTRY_L2_LEN_SHIFT; - append_size = len + ETH_HLEN + ETH_FCS_LEN; + len -= ETH_FCS_LEN; addr = (val & RCR_ENTRY_PKT_BUF_ADDR) << RCR_ENTRY_PKT_BUF_ADDR_SHIFT; @@ -3452,6 +3452,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np, RCR_ENTRY_PKTBUFSZ_SHIFT]; off = addr & ~PAGE_MASK; + append_size = rcr_size; if (num_rcr == 1) { int ptype; @@ -3464,7 +3465,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np, else skb_checksum_none_assert(skb); } else if (!(val & RCR_ENTRY_MULTI)) - append_size = append_size - skb->len; + append_size = len - skb->len; niu_rx_skb_append(skb, page, off, append_size, rcr_size); if ((page->index + rp->rbr_block_size) - rcr_size == addr) { diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index eb4d8df49399..e23a642357e7 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -60,7 +60,8 @@ #include #include "sungem.h" -#define STRIP_FCS +/* Stripping FCS is causing problems, disabled for now */ +#undef STRIP_FCS #define DEFAULT_MSG (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ @@ -434,7 +435,7 @@ static int gem_rxmac_reset(struct gem *gp) writel(desc_dma & 0xffffffff, gp->regs + RXDMA_DBLOW); writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK); val = (RXDMA_CFG_BASE | (RX_OFFSET << 10) | - (ETH_HLEN << 13) | RXDMA_CFG_FTHRESH_128); + ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_128); writel(val, gp->regs + RXDMA_CFG); if (readl(gp->regs + GREG_BIFCFG) & GREG_BIFCFG_M66EN) writel(((5 & RXDMA_BLANK_IPKTS) | @@ -759,6 +760,7 @@ static int gem_rx(struct gem *gp, int work_to_do) struct net_device *dev = gp->dev; int entry, drops, work_done = 0; u32 done; + __sum16 csum; if (netif_msg_rx_status(gp)) printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n", @@ -853,13 +855,9 @@ static int gem_rx(struct gem *gp, int work_to_do) skb = copy_skb; } - if (likely(dev->features & NETIF_F_RXCSUM)) { - __sum16 csum; - - csum = (__force __sum16)htons((status & RXDCTRL_TCPCSUM) ^ 0xffff); - skb->csum = csum_unfold(csum); - skb->ip_summed = CHECKSUM_COMPLETE; - } + csum = (__force __sum16)htons((status & RXDCTRL_TCPCSUM) ^ 0xffff); + skb->csum = csum_unfold(csum); + skb->ip_summed = CHECKSUM_COMPLETE; skb->protocol = eth_type_trans(skb, gp->dev); napi_gro_receive(&gp->napi, skb); @@ -1757,7 +1755,7 @@ static void gem_init_dma(struct gem *gp) writel(0, gp->regs + TXDMA_KICK); val = (RXDMA_CFG_BASE | (RX_OFFSET << 10) | - (ETH_HLEN << 13) | RXDMA_CFG_FTHRESH_128); + ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_128); writel(val, gp->regs + RXDMA_CFG); writel(desc_dma >> 32, gp->regs + RXDMA_DBHI); @@ -2975,8 +2973,8 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, dev); /* We can do scatter/gather and HW checksum */ - dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM; - dev->features = dev->hw_features; + dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM; + dev->features |= dev->hw_features | NETIF_F_RXCSUM; if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index b15e322b8bfe..cc106d892e29 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -1787,7 +1787,7 @@ static struct vnet *vnet_new(const u64 *local_mac, dev->ethtool_ops = &vnet_ethtool_ops; dev->watchdog_timeo = VNET_TX_TIMEOUT; - dev->hw_features = NETIF_F_TSO | NETIF_F_GSO | NETIF_F_ALL_TSO | + dev->hw_features = NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GSO_SOFTWARE | NETIF_F_HW_CSUM | NETIF_F_SG; dev->features = dev->hw_features; diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c index 7e8bce46e6b4..77d26fe286c0 100644 --- a/drivers/net/ethernet/ti/cpmac.c +++ b/drivers/net/ethernet/ti/cpmac.c @@ -549,8 +549,7 @@ static int cpmac_poll(struct napi_struct *napi, int budget) static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) { - int queue; - unsigned int len; + int queue, len; struct cpmac_desc *desc; struct cpmac_priv *priv = netdev_priv(dev); @@ -560,7 +559,7 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(skb_padto(skb, ETH_ZLEN))) return NETDEV_TX_OK; - len = max_t(unsigned int, skb->len, ETH_ZLEN); + len = max(skb->len, ETH_ZLEN); queue = skb_get_queue_mapping(skb); netif_stop_subqueue(dev, queue); @@ -1237,7 +1236,7 @@ int cpmac_init(void) goto fail_alloc; } - /* FIXME: unhardcode gpio&reset bits */ +#warning FIXME: unhardcode gpio&reset bits ar7_gpio_disable(26); ar7_gpio_disable(27); ar7_device_reset(AR7_RESET_BIT_CPMAC_LO); diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index c69b0bdd891d..fc958067d10a 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -280,10 +280,6 @@ struct cpsw_ss_regs { /* Bit definitions for the CPSW1_TS_SEQ_LTYPE register */ #define CPSW_V1_SEQ_ID_OFS_SHIFT 16 -#define CPSW_MAX_BLKS_TX 15 -#define CPSW_MAX_BLKS_TX_SHIFT 4 -#define CPSW_MAX_BLKS_RX 5 - struct cpsw_host_regs { u32 max_blks; u32 blk_cnt; @@ -882,8 +878,7 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave, /* set speed_in input in case RMII mode is used in 100Mbps */ if (phy->speed == 100) mac_control |= BIT(15); - /* in band mode only works in 10Mbps RGMII mode */ - else if ((phy->speed == 10) && phy_interface_is_rgmii(phy)) + else if (phy->speed == 10) mac_control |= BIT(18); /* In Band mode */ if (priv->rx_pause) @@ -1131,23 +1126,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) switch (priv->version) { case CPSW_VERSION_1: slave_write(slave, TX_PRIORITY_MAPPING, CPSW1_TX_PRI_MAP); - /* Increase RX FIFO size to 5 for supporting fullduplex - * flow control mode - */ - slave_write(slave, - (CPSW_MAX_BLKS_TX << CPSW_MAX_BLKS_TX_SHIFT) | - CPSW_MAX_BLKS_RX, CPSW1_MAX_BLKS); break; case CPSW_VERSION_2: case CPSW_VERSION_3: case CPSW_VERSION_4: slave_write(slave, TX_PRIORITY_MAPPING, CPSW2_TX_PRI_MAP); - /* Increase RX FIFO size to 5 for supporting fullduplex - * flow control mode - */ - slave_write(slave, - (CPSW_MAX_BLKS_TX << CPSW_MAX_BLKS_TX_SHIFT) | - CPSW_MAX_BLKS_RX, CPSW2_MAX_BLKS); break; } diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 6be315303d61..33bd3b902304 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1517,10 +1517,6 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) static int match_first_device(struct device *dev, void *data) { - if (dev->parent && dev->parent->of_node) - return of_device_is_compatible(dev->parent->of_node, - "ti,davinci_mdio"); - return !strncmp(dev_name(dev), "davinci_mdio", 12); } diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c index 399a89f30826..a274cd49afe9 100644 --- a/drivers/net/ethernet/ti/tlan.c +++ b/drivers/net/ethernet/ti/tlan.c @@ -610,8 +610,8 @@ static int tlan_probe1(struct pci_dev *pdev, long ioaddr, int irq, int rev, #ifdef CONFIG_PCI if (pdev) pci_release_regions(pdev); -err_out: #endif +err_out: if (pdev) pci_disable_device(pdev); return rc; diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig index 5d5c0c433f3e..4f5c024c6192 100644 --- a/drivers/net/ethernet/xilinx/Kconfig +++ b/drivers/net/ethernet/xilinx/Kconfig @@ -34,7 +34,6 @@ config XILINX_AXI_EMAC config XILINX_LL_TEMAC tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver" depends on (PPC || MICROBLAZE) - depends on !64BIT || BROKEN select PHYLIB ---help--- This driver supports the Xilinx 10/100/1000 LocalLink TEMAC diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c index f6108413adba..507bbb0355c2 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c @@ -218,7 +218,6 @@ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np) ret = of_mdiobus_register(bus, np1); if (ret) { mdiobus_free(bus); - lp->mii_bus = NULL; return ret; } return 0; diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 4cb8b85cbf2c..cf468c87ce57 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -100,14 +100,6 @@ /* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */ #define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT) -#ifdef __BIG_ENDIAN -#define xemaclite_readl ioread32be -#define xemaclite_writel iowrite32be -#else -#define xemaclite_readl ioread32 -#define xemaclite_writel iowrite32 -#endif - /** * struct net_local - Our private per device data * @ndev: instance of the network device @@ -166,15 +158,15 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata) u32 reg_data; /* Enable the Tx interrupts for the first Buffer */ - reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET); - xemaclite_writel(reg_data | XEL_TSR_XMIT_IE_MASK, - drvdata->base_addr + XEL_TSR_OFFSET); + reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET); + __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK, + drvdata->base_addr + XEL_TSR_OFFSET); /* Enable the Rx interrupts for the first buffer */ - xemaclite_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET); + __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET); /* Enable the Global Interrupt Enable */ - xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); + __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); } /** @@ -189,17 +181,17 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata) u32 reg_data; /* Disable the Global Interrupt Enable */ - xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); + __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); /* Disable the Tx interrupts for the first buffer */ - reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET); - xemaclite_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK), - drvdata->base_addr + XEL_TSR_OFFSET); + reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET); + __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK), + drvdata->base_addr + XEL_TSR_OFFSET); /* Disable the Rx interrupts for the first buffer */ - reg_data = xemaclite_readl(drvdata->base_addr + XEL_RSR_OFFSET); - xemaclite_writel(reg_data & (~XEL_RSR_RECV_IE_MASK), - drvdata->base_addr + XEL_RSR_OFFSET); + reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET); + __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK), + drvdata->base_addr + XEL_RSR_OFFSET); } /** @@ -331,7 +323,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, byte_count = ETH_FRAME_LEN; /* Check if the expected buffer is available */ - reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); + reg_data = __raw_readl(addr + XEL_TSR_OFFSET); if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK)) == 0) { @@ -344,7 +336,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, addr = (void __iomem __force *)((u32 __force)addr ^ XEL_BUFFER_OFFSET); - reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); + reg_data = __raw_readl(addr + XEL_TSR_OFFSET); if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK)) != 0) @@ -355,16 +347,16 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, /* Write the frame to the buffer */ xemaclite_aligned_write(data, (u32 __force *) addr, byte_count); - xemaclite_writel((byte_count & XEL_TPLR_LENGTH_MASK), - addr + XEL_TPLR_OFFSET); + __raw_writel((byte_count & XEL_TPLR_LENGTH_MASK), + addr + XEL_TPLR_OFFSET); /* Update the Tx Status Register to indicate that there is a * frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which * is used by the interrupt handler to check whether a frame * has been transmitted */ - reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); + reg_data = __raw_readl(addr + XEL_TSR_OFFSET); reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK); - xemaclite_writel(reg_data, addr + XEL_TSR_OFFSET); + __raw_writel(reg_data, addr + XEL_TSR_OFFSET); return 0; } @@ -379,7 +371,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, * * Return: Total number of bytes received */ -static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen) +static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) { void __iomem *addr; u16 length, proto_type; @@ -389,7 +381,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen) addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use); /* Verify which buffer has valid data */ - reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET); + reg_data = __raw_readl(addr + XEL_RSR_OFFSET); if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) { if (drvdata->rx_ping_pong != 0) @@ -406,28 +398,27 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen) return 0; /* No data was available */ /* Verify that buffer has valid data */ - reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET); + reg_data = __raw_readl(addr + XEL_RSR_OFFSET); if ((reg_data & XEL_RSR_RECV_DONE_MASK) != XEL_RSR_RECV_DONE_MASK) return 0; /* No data was available */ } /* Get the protocol type of the ethernet frame that arrived */ - proto_type = ((ntohl(xemaclite_readl(addr + XEL_HEADER_OFFSET + + proto_type = ((ntohl(__raw_readl(addr + XEL_HEADER_OFFSET + XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) & XEL_RPLR_LENGTH_MASK); /* Check if received ethernet frame is a raw ethernet frame * or an IP packet or an ARP packet */ - if (proto_type > ETH_DATA_LEN) { + if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) { if (proto_type == ETH_P_IP) { - length = ((ntohl(xemaclite_readl(addr + + length = ((ntohl(__raw_readl(addr + XEL_HEADER_IP_LENGTH_OFFSET + XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) & XEL_RPLR_LENGTH_MASK); - length = min_t(u16, length, ETH_DATA_LEN); length += ETH_HLEN + ETH_FCS_LEN; } else if (proto_type == ETH_P_ARP) @@ -440,17 +431,14 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen) /* Use the length in the frame, plus the header and trailer */ length = proto_type + ETH_HLEN + ETH_FCS_LEN; - if (WARN_ON(length > maxlen)) - length = maxlen; - /* Read from the EmacLite device */ xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET), data, length); /* Acknowledge the frame */ - reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET); + reg_data = __raw_readl(addr + XEL_RSR_OFFSET); reg_data &= ~XEL_RSR_RECV_DONE_MASK; - xemaclite_writel(reg_data, addr + XEL_RSR_OFFSET); + __raw_writel(reg_data, addr + XEL_RSR_OFFSET); return length; } @@ -477,14 +465,14 @@ static void xemaclite_update_address(struct net_local *drvdata, xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN); - xemaclite_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET); + __raw_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET); /* Update the MAC address in the EmacLite */ - reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); - xemaclite_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET); + reg_data = __raw_readl(addr + XEL_TSR_OFFSET); + __raw_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET); /* Wait for EmacLite to finish with the MAC address update */ - while ((xemaclite_readl(addr + XEL_TSR_OFFSET) & + while ((__raw_readl(addr + XEL_TSR_OFFSET) & XEL_TSR_PROG_MAC_ADDR) != 0) ; } @@ -617,7 +605,7 @@ static void xemaclite_rx_handler(struct net_device *dev) skb_reserve(skb, 2); - len = xemaclite_recv_data(lp, (u8 *) skb->data, len); + len = xemaclite_recv_data(lp, (u8 *) skb->data); if (!len) { dev->stats.rx_errors++; @@ -654,32 +642,32 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id) u32 tx_status; /* Check if there is Rx Data available */ - if ((xemaclite_readl(base_addr + XEL_RSR_OFFSET) & + if ((__raw_readl(base_addr + XEL_RSR_OFFSET) & XEL_RSR_RECV_DONE_MASK) || - (xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET) + (__raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET) & XEL_RSR_RECV_DONE_MASK)) xemaclite_rx_handler(dev); /* Check if the Transmission for the first buffer is completed */ - tx_status = xemaclite_readl(base_addr + XEL_TSR_OFFSET); + tx_status = __raw_readl(base_addr + XEL_TSR_OFFSET); if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) && (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) { tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK; - xemaclite_writel(tx_status, base_addr + XEL_TSR_OFFSET); + __raw_writel(tx_status, base_addr + XEL_TSR_OFFSET); tx_complete = true; } /* Check if the Transmission for the second buffer is completed */ - tx_status = xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); + tx_status = __raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) && (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) { tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK; - xemaclite_writel(tx_status, base_addr + XEL_BUFFER_OFFSET + - XEL_TSR_OFFSET); + __raw_writel(tx_status, base_addr + XEL_BUFFER_OFFSET + + XEL_TSR_OFFSET); tx_complete = true; } @@ -712,7 +700,7 @@ static int xemaclite_mdio_wait(struct net_local *lp) /* wait for the MDIO interface to not be busy or timeout after some time. */ - while (xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) & + while (__raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) & XEL_MDIOCTRL_MDIOSTS_MASK) { if (time_before_eq(end, jiffies)) { WARN_ON(1); @@ -748,17 +736,17 @@ static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg) * MDIO Address register. Set the Status bit in the MDIO Control * register to start a MDIO read transaction. */ - ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); - xemaclite_writel(XEL_MDIOADDR_OP_MASK | - ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), - lp->base_addr + XEL_MDIOADDR_OFFSET); - xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, - lp->base_addr + XEL_MDIOCTRL_OFFSET); + ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); + __raw_writel(XEL_MDIOADDR_OP_MASK | + ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), + lp->base_addr + XEL_MDIOADDR_OFFSET); + __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, + lp->base_addr + XEL_MDIOCTRL_OFFSET); if (xemaclite_mdio_wait(lp)) return -ETIMEDOUT; - rc = xemaclite_readl(lp->base_addr + XEL_MDIORD_OFFSET); + rc = __raw_readl(lp->base_addr + XEL_MDIORD_OFFSET); dev_dbg(&lp->ndev->dev, "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n", @@ -795,13 +783,13 @@ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg, * Data register. Finally, set the Status bit in the MDIO Control * register to start a MDIO write transaction. */ - ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); - xemaclite_writel(~XEL_MDIOADDR_OP_MASK & - ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), - lp->base_addr + XEL_MDIOADDR_OFFSET); - xemaclite_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET); - xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, - lp->base_addr + XEL_MDIOCTRL_OFFSET); + ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); + __raw_writel(~XEL_MDIOADDR_OP_MASK & + ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), + lp->base_addr + XEL_MDIOADDR_OFFSET); + __raw_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET); + __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, + lp->base_addr + XEL_MDIOCTRL_OFFSET); return 0; } @@ -848,8 +836,8 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) /* Enable the MDIO bus by asserting the enable bit in MDIO Control * register. */ - xemaclite_writel(XEL_MDIOCTRL_MDIOEN_MASK, - lp->base_addr + XEL_MDIOCTRL_OFFSET); + __raw_writel(XEL_MDIOCTRL_MDIOEN_MASK, + lp->base_addr + XEL_MDIOCTRL_OFFSET); bus = mdiobus_alloc(); if (!bus) { @@ -1153,8 +1141,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev) dev_warn(dev, "No MAC address found\n"); /* Clear the Tx CSR's in case this is a restart */ - xemaclite_writel(0, lp->base_addr + XEL_TSR_OFFSET); - xemaclite_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); + __raw_writel(0, lp->base_addr + XEL_TSR_OFFSET); + __raw_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); /* Set the MAC address in the EmacLite device */ xemaclite_update_address(lp, ndev->dev_addr); diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index a539e831b4b1..0ddb54fe3d91 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -1205,7 +1205,7 @@ static void fjes_netdev_setup(struct net_device *netdev) fjes_set_ethtool_ops(netdev); netdev->mtu = fjes_support_mtu[0]; netdev->flags |= IFF_BROADCAST; - netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; + netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER; } static void fjes_irq_watch_task(struct work_struct *work) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index f0961cbaf87e..58efdec12f30 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -310,15 +310,15 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) /* Need Geneve and inner Ethernet header to be present */ if (unlikely(!pskb_may_pull(skb, GENEVE_BASE_HLEN))) - goto drop; + goto error; /* Return packets with reserved bits set */ geneveh = geneve_hdr(skb); if (unlikely(geneveh->ver != GENEVE_VER)) - goto drop; + goto error; if (unlikely(geneveh->proto_type != htons(ETH_P_TEB))) - goto drop; + goto error; opts_len = geneveh->opt_len * 4; if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len, @@ -336,6 +336,10 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) /* Consume bad packet */ kfree_skb(skb); return 0; + +error: + /* Let the UDP layer deal with the skb */ + return 1; } static struct socket *geneve_create_sock(struct net *net, bool ipv6, @@ -440,7 +444,7 @@ static struct sk_buff **geneve_gro_receive(struct sk_buff **head, skb_gro_pull(skb, gh_len); skb_gro_postpull_rcsum(skb, gh, gh_len); - pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); + pp = ptype->callbacks.gro_receive(head, skb); out_unlock: rcu_read_unlock(); @@ -815,6 +819,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, struct geneve_dev *geneve = netdev_priv(dev); struct geneve_sock *gs4 = geneve->sock4; struct rtable *rt = NULL; + const struct iphdr *iip; /* interior IP header */ int err = -EINVAL; struct flowi4 fl4; __u8 tos, ttl; @@ -841,6 +846,8 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); skb_reset_mac_header(skb); + iip = ip_hdr(skb); + if (info) { const struct ip_tunnel_key *key = &info->key; u8 *opts = NULL; @@ -856,7 +863,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) goto err; - tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb); + tos = ip_tunnel_ecn_encap(key->tos, iip, skb); ttl = key->ttl; df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; } else { @@ -866,7 +873,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) goto err; - tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb); + tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, iip, skb); ttl = geneve->ttl; if (!ttl && IN_MULTICAST(ntohl(fl4.daddr))) ttl = 1; @@ -900,6 +907,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, struct geneve_dev *geneve = netdev_priv(dev); struct geneve_sock *gs6 = geneve->sock6; struct dst_entry *dst = NULL; + const struct iphdr *iip; /* interior IP header */ int err = -EINVAL; struct flowi6 fl6; __u8 prio, ttl; @@ -923,6 +931,8 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); skb_reset_mac_header(skb); + iip = ip_hdr(skb); + if (info) { const struct ip_tunnel_key *key = &info->key; u8 *opts = NULL; @@ -939,7 +949,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) goto err; - prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb); + prio = ip_tunnel_ecn_encap(key->tos, iip, skb); ttl = key->ttl; } else { udp_csum = false; @@ -948,7 +958,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) goto err; - prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, ip_hdr(skb), skb); + prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, iip, skb); ttl = geneve->ttl; if (!ttl && ipv6_addr_is_multicast(&fl6.daddr)) ttl = 1; @@ -988,17 +998,6 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) return geneve_xmit_skb(skb, dev, info); } -static int geneve_change_mtu(struct net_device *dev, int new_mtu) -{ - /* GENEVE overhead is not fixed, so we can't enforce a more - * precise max MTU. - */ - if (new_mtu < 68 || new_mtu > IP_MAX_MTU) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { struct ip_tunnel_info *info = skb_tunnel_info(skb); @@ -1043,7 +1042,7 @@ static const struct net_device_ops geneve_netdev_ops = { .ndo_stop = geneve_stop, .ndo_start_xmit = geneve_xmit, .ndo_get_stats64 = ip_tunnel_get_stats64, - .ndo_change_mtu = geneve_change_mtu, + .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_fill_metadata_dst = geneve_fill_metadata_dst, @@ -1350,21 +1349,11 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name, err = geneve_configure(net, dev, &geneve_remote_unspec, 0, 0, 0, htons(dst_port), true); - if (err) - goto err; - - /* openvswitch users expect packet sizes to be unrestricted, - * so set the largest MTU we can. - */ - err = geneve_change_mtu(dev, IP_MAX_MTU); - if (err) - goto err; - + if (err) { + free_netdev(dev); + return ERR_PTR(err); + } return dev; - - err: - free_netdev(dev); - return ERR_PTR(err); } EXPORT_SYMBOL_GPL(geneve_dev_create_fb); diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 8748e8c9ce96..d95a50ae996d 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -89,6 +89,10 @@ static const char banner[] __initconst = KERN_INFO \ "AX.25: bpqether driver version 004\n"; +static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + +static char bpq_eth_addr[6]; + static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); static int bpq_device_event(struct notifier_block *, unsigned long, void *); @@ -511,8 +515,8 @@ static int bpq_new_device(struct net_device *edev) bpq->ethdev = edev; bpq->axdev = ndev; - eth_broadcast_addr(bpq->dest_addr); - eth_broadcast_addr(bpq->acpt_addr); + memcpy(bpq->dest_addr, bcast_addr, sizeof(bpq_eth_addr)); + memcpy(bpq->acpt_addr, bcast_addr, sizeof(bpq_eth_addr)); err = register_netdevice(ndev); if (err) diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index a75ce9051a7f..49fe59b180a8 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -574,8 +574,6 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case HDLCDRVCTL_CALIBRATE: if(!capable(CAP_SYS_RAWIO)) return -EPERM; - if (s->par.bitrate <= 0) - return -EINVAL; if (bi.data.calibrate > INT_MAX / s->par.bitrate) return -EINVAL; s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16; diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 0758d0816840..85828f153445 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -648,8 +648,8 @@ static void ax_setup(struct net_device *dev) { /* Finish setting up the DEVICE info. */ dev->mtu = AX_MTU; - dev->hard_header_len = AX25_MAX_HEADER_LEN; - dev->addr_len = AX25_ADDR_LEN; + dev->hard_header_len = 0; + dev->addr_len = 0; dev->type = ARPHRD_AX25; dev->tx_queue_len = 10; dev->header_ops = &ax25_header_ops; diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c index 313e006f74fe..95c0b45a68fb 100644 --- a/drivers/net/hippi/rrunner.c +++ b/drivers/net/hippi/rrunner.c @@ -1381,8 +1381,8 @@ static int rr_close(struct net_device *dev) rrpriv->info_dma); rrpriv->info = NULL; - spin_unlock_irqrestore(&rrpriv->lock, flags); free_irq(pdev->irq, dev); + spin_unlock_irqrestore(&rrpriv->lock, flags); return 0; } diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index c8a7802d2953..409b48e1e589 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -40,8 +40,6 @@ #include "hyperv_net.h" -/* Restrict GSO size to account for NVGRE */ -#define NETVSC_GSO_MAX_SIZE 62768 #define RING_SIZE_MIN 64 static int ring_size = 128; @@ -197,6 +195,65 @@ static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size, return ppi; } +union sub_key { + u64 k; + struct { + u8 pad[3]; + u8 kb; + u32 ka; + }; +}; + +/* Toeplitz hash function + * data: network byte order + * return: host byte order + */ +static u32 comp_hash(u8 *key, int klen, void *data, int dlen) +{ + union sub_key subk; + int k_next = 4; + u8 dt; + int i, j; + u32 ret = 0; + + subk.k = 0; + subk.ka = ntohl(*(u32 *)key); + + for (i = 0; i < dlen; i++) { + subk.kb = key[k_next]; + k_next = (k_next + 1) % klen; + dt = ((u8 *)data)[i]; + for (j = 0; j < 8; j++) { + if (dt & 0x80) + ret ^= subk.ka; + dt <<= 1; + subk.k <<= 1; + } + } + + return ret; +} + +static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb) +{ + struct flow_keys flow; + int data_len; + + if (!skb_flow_dissect_flow_keys(skb, &flow, 0) || + !(flow.basic.n_proto == htons(ETH_P_IP) || + flow.basic.n_proto == htons(ETH_P_IPV6))) + return false; + + if (flow.basic.ip_proto == IPPROTO_TCP) + data_len = 12; + else + data_len = 8; + + *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, &flow, data_len); + + return true; +} + static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, void *accel_priv, select_queue_fallback_t fallback) { @@ -209,9 +266,11 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1) return 0; - hash = skb_get_hash(skb); - q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] % - ndev->real_num_tx_queues; + if (netvsc_set_hash(&hash, skb)) { + q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] % + ndev->real_num_tx_queues; + skb_set_hash(skb, hash, PKT_HASH_TYPE_L3); + } return q_idx; } @@ -1080,7 +1139,6 @@ static int netvsc_probe(struct hv_device *dev, nvdev = hv_get_drvdata(dev); netif_set_real_num_tx_queues(net, nvdev->num_chn); netif_set_real_num_rx_queues(net, nvdev->num_chn); - netif_set_gso_max_size(net, NETVSC_GSO_MAX_SIZE); ret = register_netdev(net); if (ret != 0) { diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index f72c2967ae82..0fbbba7a0cae 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -932,7 +932,7 @@ at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb) static int at86rf230_ed(struct ieee802154_hw *hw, u8 *level) { - WARN_ON(!level); + BUG_ON(!level); *level = 0xbe; return 0; } @@ -1108,7 +1108,8 @@ at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw, if (changed & IEEE802154_AFILT_SADDR_CHANGED) { u16 addr = le16_to_cpu(filt->short_addr); - dev_vdbg(&lp->spi->dev, "%s called for saddr\n", __func__); + dev_vdbg(&lp->spi->dev, + "at86rf230_set_hw_addr_filt called for saddr\n"); __at86rf230_write(lp, RG_SHORT_ADDR_0, addr); __at86rf230_write(lp, RG_SHORT_ADDR_1, addr >> 8); } @@ -1116,7 +1117,8 @@ at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw, if (changed & IEEE802154_AFILT_PANID_CHANGED) { u16 pan = le16_to_cpu(filt->pan_id); - dev_vdbg(&lp->spi->dev, "%s called for pan id\n", __func__); + dev_vdbg(&lp->spi->dev, + "at86rf230_set_hw_addr_filt called for pan id\n"); __at86rf230_write(lp, RG_PAN_ID_0, pan); __at86rf230_write(lp, RG_PAN_ID_1, pan >> 8); } @@ -1125,13 +1127,15 @@ at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw, u8 i, addr[8]; memcpy(addr, &filt->ieee_addr, 8); - dev_vdbg(&lp->spi->dev, "%s called for IEEE addr\n", __func__); + dev_vdbg(&lp->spi->dev, + "at86rf230_set_hw_addr_filt called for IEEE addr\n"); for (i = 0; i < 8; i++) __at86rf230_write(lp, RG_IEEE_ADDR_0 + i, addr[i]); } if (changed & IEEE802154_AFILT_PANC_CHANGED) { - dev_vdbg(&lp->spi->dev, "%s called for panc change\n", __func__); + dev_vdbg(&lp->spi->dev, + "at86rf230_set_hw_addr_filt called for panc change\n"); if (filt->pan_coord) at86rf230_write_subreg(lp, SR_AACK_I_AM_COORD, 1); else @@ -1235,6 +1239,7 @@ at86rf230_set_cca_mode(struct ieee802154_hw *hw, return at86rf230_write_subreg(lp, SR_CCA_MODE, val); } + static int at86rf230_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm) { diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 3a429f1a8002..199a94a9c8bc 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -110,26 +110,13 @@ static int atusb_read_reg(struct atusb *atusb, uint8_t reg) { struct usb_device *usb_dev = atusb->usb_dev; int ret; - uint8_t *buffer; uint8_t value; - buffer = kmalloc(1, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - dev_dbg(&usb_dev->dev, "atusb: reg = 0x%x\n", reg); ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0), ATUSB_REG_READ, ATUSB_REQ_FROM_DEV, - 0, reg, buffer, 1, 1000); - - if (ret >= 0) { - value = buffer[0]; - kfree(buffer); - return value; - } else { - kfree(buffer); - return ret; - } + 0, reg, &value, 1, 1000); + return ret >= 0 ? value : ret; } static int atusb_write_subreg(struct atusb *atusb, uint8_t reg, uint8_t mask, @@ -530,13 +517,9 @@ static struct ieee802154_ops atusb_ops = { static int atusb_get_and_show_revision(struct atusb *atusb) { struct usb_device *usb_dev = atusb->usb_dev; - unsigned char *buffer; + unsigned char buffer[3]; int ret; - buffer = kmalloc(3, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - /* Get a couple of the ATMega Firmware values */ ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0), ATUSB_ID, ATUSB_REQ_FROM_DEV, 0, 0, @@ -552,20 +535,15 @@ static int atusb_get_and_show_revision(struct atusb *atusb) dev_info(&usb_dev->dev, "Please update to version 0.2 or newer"); } - kfree(buffer); return ret; } static int atusb_get_and_show_build(struct atusb *atusb) { struct usb_device *usb_dev = atusb->usb_dev; - char *build; + char build[ATUSB_BUILD_SIZE + 1]; int ret; - build = kmalloc(ATUSB_BUILD_SIZE + 1, GFP_KERNEL); - if (!build) - return -ENOMEM; - ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0), ATUSB_BUILD, ATUSB_REQ_FROM_DEV, 0, 0, build, ATUSB_BUILD_SIZE, 1000); @@ -574,7 +552,6 @@ static int atusb_get_and_show_build(struct atusb *atusb) dev_info(&usb_dev->dev, "Firmware: build %s\n", build); } - kfree(build); return ret; } diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c index 91de25c53274..860d4aed8274 100644 --- a/drivers/net/ieee802154/fakelb.c +++ b/drivers/net/ieee802154/fakelb.c @@ -30,7 +30,7 @@ static int numlbs = 2; static LIST_HEAD(fakelb_phys); -static DEFINE_MUTEX(fakelb_phys_lock); +static DEFINE_SPINLOCK(fakelb_phys_lock); static LIST_HEAD(fakelb_ifup_phys); static DEFINE_RWLOCK(fakelb_ifup_phys_lock); @@ -49,7 +49,7 @@ struct fakelb_phy { static int fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level) { - WARN_ON(!level); + BUG_ON(!level); *level = 0xbe; return 0; @@ -180,9 +180,9 @@ static int fakelb_add_one(struct device *dev) if (err) goto err_reg; - mutex_lock(&fakelb_phys_lock); + spin_lock(&fakelb_phys_lock); list_add_tail(&phy->list, &fakelb_phys); - mutex_unlock(&fakelb_phys_lock); + spin_unlock(&fakelb_phys_lock); return 0; @@ -214,10 +214,10 @@ static int fakelb_probe(struct platform_device *pdev) return 0; err_slave: - mutex_lock(&fakelb_phys_lock); + spin_lock(&fakelb_phys_lock); list_for_each_entry_safe(phy, tmp, &fakelb_phys, list) fakelb_del(phy); - mutex_unlock(&fakelb_phys_lock); + spin_unlock(&fakelb_phys_lock); return err; } @@ -225,10 +225,10 @@ static int fakelb_remove(struct platform_device *pdev) { struct fakelb_phy *phy, *tmp; - mutex_lock(&fakelb_phys_lock); + spin_lock(&fakelb_phys_lock); list_for_each_entry_safe(phy, tmp, &fakelb_phys, list) fakelb_del(phy); - mutex_unlock(&fakelb_phys_lock); + spin_unlock(&fakelb_phys_lock); return 0; } diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 142015af43db..8c48bb2a94ea 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -282,10 +282,6 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff **pskb, if (dev_forward_skb(ipvlan->dev, skb) == NET_RX_SUCCESS) success = true; } else { - if (!ether_addr_equal_64bits(eth_hdr(skb)->h_dest, - ipvlan->phy_dev->dev_addr)) - skb->pkt_type = PACKET_OTHERHOST; - ret = RX_HANDLER_ANOTHER; success = true; } @@ -357,7 +353,6 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb) .flowi4_oif = dev->ifindex, .flowi4_tos = RT_TOS(ip4h->tos), .flowi4_flags = FLOWI_FLAG_ANYSRC, - .flowi4_mark = skb->mark, .daddr = ip4h->daddr, .saddr = ip4h->saddr, }; @@ -393,7 +388,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb) struct dst_entry *dst; int err, ret = NET_XMIT_DROP; struct flowi6 fl6 = { - .flowi6_oif = dev->ifindex, + .flowi6_iif = dev->ifindex, .daddr = ip6h->daddr, .saddr = ip6h->saddr, .flowi6_flags = FLOWI_FLAG_ANYSRC, diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index de2ea9f2f966..25f21968fa5c 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1077,7 +1077,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self) * are "42101001.sb" or "42101002.sb" */ sprintf(stir421x_fw_name, "4210%4X.sb", - le16_to_cpu(self->usbdev->descriptor.bcdDevice)); + self->usbdev->descriptor.bcdDevice); ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev); if (ret < 0) return ret; diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c index e1bb802d4a4d..bca6a1e72d1d 100644 --- a/drivers/net/irda/mcs7780.c +++ b/drivers/net/irda/mcs7780.c @@ -141,19 +141,9 @@ static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val) static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val) { struct usb_device *dev = mcs->usbdev; - void *dmabuf; - int ret; - - dmabuf = kmalloc(sizeof(__u16), GFP_KERNEL); - if (!dmabuf) - return -ENOMEM; - - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, - MCS_RD_RTYPE, 0, reg, dmabuf, 2, - msecs_to_jiffies(MCS_CTRL_TIMEOUT)); - - memcpy(val, dmabuf, sizeof(__u16)); - kfree(dmabuf); + int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, + MCS_RD_RTYPE, 0, reg, val, 2, + msecs_to_jiffies(MCS_CTRL_TIMEOUT)); return ret; } diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index c0192f97ecc8..a0849f49bbec 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -418,9 +418,8 @@ static struct vlsi_ring *vlsi_alloc_ring(struct pci_dev *pdev, struct ring_descr memset(rd, 0, sizeof(*rd)); rd->hw = hwmap + i; rd->buf = kmalloc(len, GFP_KERNEL|GFP_DMA); - if (rd->buf) - busaddr = pci_map_single(pdev, rd->buf, len, dir); - if (rd->buf == NULL || pci_dma_mapping_error(pdev, busaddr)) { + if (rd->buf == NULL || + !(busaddr = pci_map_single(pdev, rd->buf, len, dir))) { if (rd->buf) { net_err_ratelimited("%s: failed to create PCI-MAP for %p\n", __func__, rd->buf); @@ -431,7 +430,8 @@ static struct vlsi_ring *vlsi_alloc_ring(struct pci_dev *pdev, struct ring_descr rd = r->rd + j; busaddr = rd_get_addr(rd); rd_set_addr_status(rd, 0, 0); - pci_unmap_single(pdev, busaddr, len, dir); + if (busaddr) + pci_unmap_single(pdev, busaddr, len, dir); kfree(rd->buf); rd->buf = NULL; } diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c index e8c3a8c32534..4e3d2e7c697c 100644 --- a/drivers/net/irda/w83977af_ir.c +++ b/drivers/net/irda/w83977af_ir.c @@ -518,9 +518,7 @@ static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb, mtt = irda_get_mtt(skb); pr_debug("%s(%ld), mtt=%d\n", __func__ , jiffies, mtt); - if (mtt > 1000) - mdelay(mtt/1000); - else if (mtt) + if (mtt) udelay(mtt); /* Enable DMA interrupt */ diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index effcdbfb06e9..dc7d970bd1c0 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -164,7 +164,6 @@ static void loopback_setup(struct net_device *dev) { dev->mtu = 64 * 1024; dev->hard_header_len = ETH_HLEN; /* 14 */ - dev->min_header_len = ETH_HLEN; /* 14 */ dev->addr_len = ETH_ALEN; /* 6 */ dev->type = ARPHRD_LOOPBACK; /* 0x0001*/ dev->flags = IFF_LOOPBACK; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 9897cabec371..06c8bfeaccd6 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -441,7 +441,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) struct macvlan_dev, list); else vlan = macvlan_hash_lookup(port, eth->h_dest); - if (!vlan || vlan->mode == MACVLAN_MODE_SOURCE) + if (vlan == NULL) return RX_HANDLER_PASS; dev = vlan->dev; @@ -1110,7 +1110,6 @@ static int macvlan_port_create(struct net_device *dev) static void macvlan_port_destroy(struct net_device *dev) { struct macvlan_port *port = macvlan_port_get_rtnl(dev); - struct sk_buff *skb; dev->priv_flags &= ~IFF_MACVLAN_PORT; netdev_rx_handler_unregister(dev); @@ -1119,15 +1118,7 @@ static void macvlan_port_destroy(struct net_device *dev) * but we need to cancel it and purge left skbs if any. */ cancel_work_sync(&port->bc_work); - - while ((skb = __skb_dequeue(&port->bc_queue))) { - const struct macvlan_dev *src = MACVLAN_SKB_CB(skb)->src; - - if (src) - dev_put(src->dev); - - kfree_skb(skb); - } + __skb_queue_purge(&port->bc_queue); kfree_rcu(port, rcu); } diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index ed96fdefd8e5..159a68782bec 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -725,7 +725,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, ssize_t n; if (q->flags & IFF_VNET_HDR) { - vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz); + vnet_hdr_len = q->vnet_hdr_sz; err = -EINVAL; if (len < vnet_hdr_len) @@ -865,7 +865,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, if (q->flags & IFF_VNET_HDR) { struct virtio_net_hdr vnet_hdr; - vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz); + vnet_hdr_len = q->vnet_hdr_sz; if (iov_iter_count(iter) < vnet_hdr_len) return -EINVAL; @@ -1117,8 +1117,6 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, case TUNSETSNDBUF: if (get_user(s, sp)) return -EFAULT; - if (s <= 0) - return -EINVAL; q->sk.sk_sndbuf = s; return 0; diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 37333d38b576..2d020a3ec0b5 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -105,7 +105,7 @@ static int at803x_set_wol(struct phy_device *phydev, mac = (const u8 *) ndev->dev_addr; if (!is_valid_ether_addr(mac)) - return -EINVAL; + return -EFAULT; for (i = 0; i < 3; i++) { phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, diff --git a/drivers/net/phy/bcm-cygnus.c b/drivers/net/phy/bcm-cygnus.c index 9a7dca2bb618..49bbc6826883 100644 --- a/drivers/net/phy/bcm-cygnus.c +++ b/drivers/net/phy/bcm-cygnus.c @@ -61,17 +61,17 @@ static int bcm_cygnus_afe_config(struct phy_device *phydev) return rc; /* make rcal=100, since rdb default is 000 */ - rc = bcm_phy_write_exp_sel(phydev, MII_BRCM_CORE_EXPB1, 0x10); + rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB1, 0x10); if (rc < 0) return rc; /* CORE_EXPB0, Reset R_CAL/RC_CAL Engine */ - rc = bcm_phy_write_exp_sel(phydev, MII_BRCM_CORE_EXPB0, 0x10); + rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x10); if (rc < 0) return rc; /* CORE_EXPB0, Disable Reset R_CAL/RC_CAL Engine */ - rc = bcm_phy_write_exp_sel(phydev, MII_BRCM_CORE_EXPB0, 0x00); + rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x00); return 0; } diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h index ce16b26d49ff..b2091c88b44d 100644 --- a/drivers/net/phy/bcm-phy-lib.h +++ b/drivers/net/phy/bcm-phy-lib.h @@ -14,18 +14,11 @@ #ifndef _LINUX_BCM_PHY_LIB_H #define _LINUX_BCM_PHY_LIB_H -#include #include int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val); int bcm_phy_read_exp(struct phy_device *phydev, u16 reg); -static inline int bcm_phy_write_exp_sel(struct phy_device *phydev, - u16 reg, u16 val) -{ - return bcm_phy_write_exp(phydev, reg | MII_BCM54XX_EXP_SEL_ER, val); -} - int bcm_phy_write_misc(struct phy_device *phydev, u16 reg, u16 chl, u16 value); int bcm_phy_read_misc(struct phy_device *phydev, diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c index 9b709f78bb03..86b28052bf06 100644 --- a/drivers/net/phy/bcm63xx.c +++ b/drivers/net/phy/bcm63xx.c @@ -21,23 +21,6 @@ MODULE_DESCRIPTION("Broadcom 63xx internal PHY driver"); MODULE_AUTHOR("Maxime Bizon "); MODULE_LICENSE("GPL"); -static int bcm63xx_config_intr(struct phy_device *phydev) -{ - int reg, err; - - reg = phy_read(phydev, MII_BCM63XX_IR); - if (reg < 0) - return reg; - - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) - reg &= ~MII_BCM63XX_IR_GMASK; - else - reg |= MII_BCM63XX_IR_GMASK; - - err = phy_write(phydev, MII_BCM63XX_IR, reg); - return err; -} - static int bcm63xx_config_init(struct phy_device *phydev) { int reg, err; @@ -72,7 +55,7 @@ static struct phy_driver bcm63xx_driver[] = { .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = bcm_phy_ack_intr, - .config_intr = bcm63xx_config_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { /* same phy as above, with just a different OUI */ @@ -85,7 +68,7 @@ static struct phy_driver bcm63xx_driver[] = { .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = bcm_phy_ack_intr, - .config_intr = bcm63xx_config_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, } }; diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index bffa70e46202..03d4809a9126 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -48,10 +48,10 @@ static void r_rc_cal_reset(struct phy_device *phydev) { /* Reset R_CAL/RC_CAL Engine */ - bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0010); + bcm_phy_write_exp(phydev, 0x00b0, 0x0010); /* Disable Reset R_AL/RC_CAL Engine */ - bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0000); + bcm_phy_write_exp(phydev, 0x00b0, 0x0000); } static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index dc934347ae28..e6cefd0e3262 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -907,7 +907,7 @@ static void decode_txts(struct dp83640_private *dp83640, if (overflow) { pr_debug("tx timestamp queue overflow, count %d\n", overflow); while (skb) { - kfree_skb(skb); + skb_complete_tx_timestamp(skb, NULL); skb = skb_dequeue(&dp83640->tx_queue); } return; @@ -1203,23 +1203,6 @@ static void dp83640_remove(struct phy_device *phydev) kfree(dp83640); } -static int dp83640_soft_reset(struct phy_device *phydev) -{ - int ret; - - ret = genphy_soft_reset(phydev); - if (ret < 0) - return ret; - - /* From DP83640 datasheet: "Software driver code must wait 3 us - * following a software reset before allowing further serial MII - * operations with the DP83640." - */ - udelay(10); /* Taking udelay inaccuracy into account */ - - return 0; -} - static int dp83640_config_init(struct phy_device *phydev) { struct dp83640_private *dp83640 = phydev->priv; @@ -1453,6 +1436,8 @@ static bool dp83640_rxtstamp(struct phy_device *phydev, skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT; skb_queue_tail(&dp83640->rx_queue, skb); schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT); + } else { + netif_rx_ni(skb); } return true; @@ -1513,7 +1498,6 @@ static struct phy_driver dp83640_driver = { .flags = PHY_HAS_INTERRUPT, .probe = dp83640_probe, .remove = dp83640_remove, - .soft_reset = dp83640_soft_reset, .config_init = dp83640_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 7242dd4b3238..32f10662f4ac 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -29,7 +29,6 @@ #define MII_DP83867_MICR 0x12 #define MII_DP83867_ISR 0x13 #define DP83867_CTRL 0x1f -#define DP83867_CFG3 0x1e /* Extended Registers */ #define DP83867_RGMIICTL 0x0032 @@ -90,8 +89,6 @@ static int dp83867_config_intr(struct phy_device *phydev) micr_status |= (MII_DP83867_MICR_AN_ERR_INT_EN | MII_DP83867_MICR_SPEED_CHNG_INT_EN | - MII_DP83867_MICR_AUTONEG_COMP_INT_EN | - MII_DP83867_MICR_LINK_STS_CHNG_INT_EN | MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN | MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN); @@ -187,13 +184,6 @@ static int dp83867_config_init(struct phy_device *phydev) DP83867_DEVADDR, phydev->addr, delay); } - /* Enable Interrupt output INT_OE in CFG3 register */ - if (phy_interrupt_is_valid(phydev)) { - val = phy_read(phydev, DP83867_CFG3); - val |= BIT(7); - phy_write(phydev, DP83867_CFG3, val); - } - return 0; } diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index ebec2dceff45..0240552b50f3 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -203,6 +203,34 @@ static int marvell_config_aneg(struct phy_device *phydev) { int err; + /* The Marvell PHY has an errata which requires + * that certain registers get written in order + * to restart autonegotiation */ + err = phy_write(phydev, MII_BMCR, BMCR_RESET); + + if (err < 0) + return err; + + err = phy_write(phydev, 0x1d, 0x1f); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0x200c); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1d, 0x5); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0x100); + if (err < 0) + return err; + err = marvell_set_polarity(phydev, phydev->mdix); if (err < 0) return err; @@ -236,42 +264,6 @@ static int marvell_config_aneg(struct phy_device *phydev) return 0; } -static int m88e1101_config_aneg(struct phy_device *phydev) -{ - int err; - - /* This Marvell PHY has an errata which requires - * that certain registers get written in order - * to restart autonegotiation - */ - err = phy_write(phydev, MII_BMCR, BMCR_RESET); - - if (err < 0) - return err; - - err = phy_write(phydev, 0x1d, 0x1f); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0x200c); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1d, 0x5); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0x100); - if (err < 0) - return err; - - return marvell_config_aneg(phydev); -} - #ifdef CONFIG_OF_MDIO /* * Set and/or override some configuration registers based on the @@ -822,6 +814,8 @@ static int marvell_read_status(struct phy_device *phydev) phydev->lp_advertising = mii_stat1000_to_ethtool_lpa_t(lpagb) | mii_lpa_to_ethtool_lpa_t(lpa); + lpa &= adv; + if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) phydev->duplex = DUPLEX_FULL; else @@ -999,7 +993,7 @@ static struct phy_driver marvell_drivers[] = { .name = "Marvell 88E1101", .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, - .config_aneg = &m88e1101_config_aneg, + .config_aneg = &marvell_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &marvell_ack_interrupt, .config_intr = &marvell_config_intr, diff --git a/drivers/net/phy/mdio-bcm-iproc.c b/drivers/net/phy/mdio-bcm-iproc.c index 46fe1ae919a3..c0b4e65267af 100644 --- a/drivers/net/phy/mdio-bcm-iproc.c +++ b/drivers/net/phy/mdio-bcm-iproc.c @@ -81,6 +81,8 @@ static int iproc_mdio_read(struct mii_bus *bus, int phy_id, int reg) if (rc) return rc; + iproc_mdio_config_clk(priv->base); + /* Prepare the read operation */ cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) | (reg << MII_DATA_RA_SHIFT) | @@ -110,6 +112,8 @@ static int iproc_mdio_write(struct mii_bus *bus, int phy_id, if (rc) return rc; + iproc_mdio_config_clk(priv->base); + /* Prepare the write operation */ cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) | (reg << MII_DATA_RA_SHIFT) | @@ -159,8 +163,6 @@ static int iproc_mdio_probe(struct platform_device *pdev) bus->read = iproc_mdio_read; bus->write = iproc_mdio_write; - iproc_mdio_config_clk(priv->base); - rc = of_mdiobus_register(bus, pdev->dev.of_node); if (rc) { dev_err(&pdev->dev, "MDIO bus registration failed\n"); diff --git a/drivers/net/phy/mdio-sun4i.c b/drivers/net/phy/mdio-sun4i.c index afd76e07088b..15bc7f9ea224 100644 --- a/drivers/net/phy/mdio-sun4i.c +++ b/drivers/net/phy/mdio-sun4i.c @@ -128,10 +128,8 @@ static int sun4i_mdio_probe(struct platform_device *pdev) data->regulator = devm_regulator_get(&pdev->dev, "phy"); if (IS_ERR(data->regulator)) { - if (PTR_ERR(data->regulator) == -EPROBE_DEFER) { - ret = -EPROBE_DEFER; - goto err_out_free_mdiobus; - } + if (PTR_ERR(data->regulator) == -EPROBE_DEFER) + return -EPROBE_DEFER; dev_info(&pdev->dev, "no regulator found\n"); } else { diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 920391165f18..e13ad6cdcc22 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -539,9 +539,6 @@ static int ksz9031_read_status(struct phy_device *phydev) if ((regval & 0xFF) == 0xFF) { phy_init_hw(phydev); phydev->link = 0; - if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev)) - phydev->drv->config_intr(phydev); - return genphy_config_aneg(phydev); } return 0; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 7d2cf015c5e7..47cd306dbb3c 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -148,12 +148,6 @@ static inline int phy_aneg_done(struct phy_device *phydev) if (phydev->drv->aneg_done) return phydev->drv->aneg_done(phydev); - /* Avoid genphy_aneg_done() if the Clause 45 PHY does not - * implement Clause 22 registers - */ - if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0))) - return -EINVAL; - return genphy_aneg_done(phydev); } @@ -544,7 +538,7 @@ void phy_stop_machine(struct phy_device *phydev) cancel_delayed_work_sync(&phydev->state_queue); mutex_lock(&phydev->lock); - if (phydev->state > PHY_UP && phydev->state != PHY_HALTED) + if (phydev->state > PHY_UP) phydev->state = PHY_UP; mutex_unlock(&phydev->lock); } @@ -646,10 +640,8 @@ static int phy_disable_interrupts(struct phy_device *phydev) int phy_start_interrupts(struct phy_device *phydev) { atomic_set(&phydev->irq_disable, 0); - if (request_irq(phydev->irq, phy_interrupt, - IRQF_SHARED, - "phy_interrupt", - phydev) < 0) { + if (request_irq(phydev->irq, phy_interrupt, 0, "phy_interrupt", + phydev) < 0) { pr_warn("%s: Can't get IRQ %d (PHY)\n", phydev->bus->name, phydev->irq); phydev->irq = PHY_POLL; @@ -924,15 +916,6 @@ void phy_state_machine(struct work_struct *work) if (old_link != phydev->link) phydev->state = PHY_CHANGELINK; } - /* - * Failsafe: check that nobody set phydev->link=0 between two - * poll cycles, otherwise we won't leave RUNNING state as long - * as link remains down. - */ - if (!phydev->link && phydev->state == PHY_RUNNING) { - phydev->state = PHY_CHANGELINK; - dev_err(&phydev->dev, "no link in PHY_RUNNING\n"); - } break; case PHY_CHANGELINK: err = phy_read_status(phydev); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 1f2f25a71d18..0bfbabad4431 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1265,8 +1265,11 @@ static int gen10g_resume(struct phy_device *phydev) static int __set_phy_supported(struct phy_device *phydev, u32 max_speed) { - phydev->supported &= ~(PHY_1000BT_FEATURES | PHY_100BT_FEATURES | - PHY_10BT_FEATURES); + /* The default values for phydev->supported are provided by the PHY + * driver "features" member, we want to reset to sane defaults first + * before supporting higher speeds. + */ + phydev->supported &= PHY_DEFAULT_FEATURES; switch (max_speed) { default: @@ -1365,8 +1368,6 @@ static int phy_remove(struct device *dev) { struct phy_device *phydev = to_phy_device(dev); - cancel_delayed_work_sync(&phydev->state_queue); - mutex_lock(&phydev->lock); phydev->state = PHY_DOWN; mutex_unlock(&phydev->lock); @@ -1441,7 +1442,7 @@ static struct phy_driver genphy_driver[] = { .phy_id = 0xffffffff, .phy_id_mask = 0xffffffff, .name = "Generic PHY", - .soft_reset = genphy_no_soft_reset, + .soft_reset = genphy_soft_reset, .config_init = genphy_config_init, .features = PHY_GBIT_FEATURES | SUPPORTED_MII | SUPPORTED_AUI | SUPPORTED_FIBRE | diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index 21d22f86134e..c72c42206850 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -310,7 +310,6 @@ static int ks8995_probe(struct spi_device *spi) if (err) return err; - sysfs_attr_init(&ks->regs_attr.attr); err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr); if (err) { dev_err(&spi->dev, "unable to create sysfs file, err=%d\n", diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 46448d7e3290..174e06ec7c2f 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -942,7 +942,6 @@ static __net_exit void ppp_exit_net(struct net *net) unregister_netdevice_many(&list); rtnl_unlock(); - mutex_destroy(&pn->all_ppp_mutex); idr_destroy(&pn->units_idr); } @@ -1111,17 +1110,7 @@ ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) static struct lock_class_key ppp_tx_busylock; static int ppp_dev_init(struct net_device *dev) { - struct ppp *ppp; - dev->qdisc_tx_busylock = &ppp_tx_busylock; - - ppp = netdev_priv(dev); - /* Let the netdevice take a reference on the ppp file. This ensures - * that ppp_destroy_interface() won't run before the device gets - * unregistered. - */ - atomic_inc(&ppp->file.refcnt); - return 0; } @@ -1144,15 +1133,6 @@ static void ppp_dev_uninit(struct net_device *dev) wake_up_interruptible(&ppp->file.rwait); } -static void ppp_dev_priv_destructor(struct net_device *dev) -{ - struct ppp *ppp; - - ppp = netdev_priv(dev); - if (atomic_dec_and_test(&ppp->file.refcnt)) - ppp_destroy_interface(ppp); -} - static const struct net_device_ops ppp_netdev_ops = { .ndo_init = ppp_dev_init, .ndo_uninit = ppp_dev_uninit, @@ -1170,7 +1150,6 @@ static void ppp_setup(struct net_device *dev) dev->tx_queue_len = 3; dev->type = ARPHRD_PPP; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; - dev->destructor = ppp_dev_priv_destructor; netif_keep_dst(dev); } @@ -2411,6 +2390,8 @@ ppp_unregister_channel(struct ppp_channel *chan) spin_lock_bh(&pn->all_channels_lock); list_del(&pch->list); spin_unlock_bh(&pn->all_channels_lock); + put_net(pch->chan_net); + pch->chan_net = NULL; pch->file.dead = 1; wake_up_interruptible(&pch->file.rwait); @@ -2952,15 +2933,6 @@ ppp_connect_channel(struct channel *pch, int unit) goto outl; ppp_lock(ppp); - spin_lock_bh(&pch->downl); - if (!pch->chan) { - /* Don't connect unregistered channels */ - spin_unlock_bh(&pch->downl); - ppp_unlock(ppp); - ret = -ENOTCONN; - goto outl; - } - spin_unlock_bh(&pch->downl); if (pch->file.hdrlen > ppp->file.hdrlen) ppp->file.hdrlen = pch->file.hdrlen; hdrlen = pch->file.hdrlen + 2; /* for protocol bytes */ @@ -3012,9 +2984,6 @@ ppp_disconnect_channel(struct channel *pch) */ static void ppp_destroy_channel(struct channel *pch) { - put_net(pch->chan_net); - pch->chan_net = NULL; - atomic_dec(&channel_count); if (!pch->file.dead) { diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 583d50f80b24..4e0068e775f9 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -638,10 +638,6 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, lock_sock(sk); error = -EINVAL; - - if (sockaddr_len != sizeof(struct sockaddr_pppox)) - goto end; - if (sp->sa_protocol != PX_PROTO_OE) goto end; @@ -864,7 +860,6 @@ static int pppoe_sendmsg(struct socket *sock, struct msghdr *m, struct pppoe_hdr *ph; struct net_device *dev; char *start; - int hlen; lock_sock(sk); if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) { @@ -883,16 +878,16 @@ static int pppoe_sendmsg(struct socket *sock, struct msghdr *m, if (total_len > (dev->mtu + dev->hard_header_len)) goto end; - hlen = LL_RESERVED_SPACE(dev); - skb = sock_wmalloc(sk, hlen + sizeof(*ph) + total_len + - dev->needed_tailroom, 0, GFP_KERNEL); + + skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32, + 0, GFP_KERNEL); if (!skb) { error = -ENOMEM; goto end; } /* Reserve space for headers. */ - skb_reserve(skb, hlen); + skb_reserve(skb, dev->hard_header_len); skb_reset_network_header(skb); skb->dev = dev; @@ -953,7 +948,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) /* Copy the data if there is no space for the header or if it's * read-only. */ - if (skb_cow_head(skb, LL_RESERVED_SPACE(dev) + sizeof(*ph))) + if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len)) goto abort; __skb_push(skb, sizeof(*ph)); diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 12a627fcc02c..f7e8c79349ad 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -501,6 +501,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.mtu = dst_mtu(&rt->dst); if (!po->chan.mtu) po->chan.mtu = PPP_MRU; + ip_rt_put(rt); po->chan.mtu -= PPTP_HEADER_OVERHEAD; po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header); diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c index cfd81eb1b532..27ed25252aac 100644 --- a/drivers/net/slip/slhc.c +++ b/drivers/net/slip/slhc.c @@ -509,10 +509,6 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize) if(x < 0 || x > comp->rslot_limit) goto bad; - /* Check if the cstate is initialized */ - if (!comp->rstate[x].initialized) - goto bad; - comp->flags &=~ SLF_TOSS; comp->recv_current = x; } else { @@ -677,7 +673,6 @@ slhc_remember(struct slcompress *comp, unsigned char *icp, int isize) if (cs->cs_tcp.doff > 5) memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4); cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2; - cs->initialized = true; /* Put headers back on packet * Neither header checksum is recalculated */ diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 49174837c2ba..59fefca74263 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -247,17 +247,6 @@ static void __team_option_inst_mark_removed_port(struct team *team, } } -static bool __team_option_inst_tmp_find(const struct list_head *opts, - const struct team_option_inst *needle) -{ - struct team_option_inst *opt_inst; - - list_for_each_entry(opt_inst, opts, tmp_list) - if (opt_inst == needle) - return true; - return false; -} - static int __team_options_register(struct team *team, const struct team_option *option, size_t option_count) @@ -980,11 +969,10 @@ static void team_port_disable(struct team *team, NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \ NETIF_F_HIGHDMA | NETIF_F_LRO) -static void ___team_compute_features(struct team *team) +static void __team_compute_features(struct team *team) { struct team_port *port; - netdev_features_t vlan_features = TEAM_VLAN_FEATURES & - NETIF_F_ALL_FOR_ALL; + u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL; unsigned short max_hard_header_len = ETH_HLEN; unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM; @@ -1005,20 +993,15 @@ static void ___team_compute_features(struct team *team) team->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; if (dst_release_flag == (IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM)) team->dev->priv_flags |= IFF_XMIT_DST_RELEASE; -} -static void __team_compute_features(struct team *team) -{ - ___team_compute_features(team); netdev_change_features(team->dev); } static void team_compute_features(struct team *team) { mutex_lock(&team->lock); - ___team_compute_features(team); + __team_compute_features(team); mutex_unlock(&team->lock); - netdev_change_features(team->dev); } static int team_port_enter(struct team *team, struct team_port *port) @@ -1051,11 +1034,14 @@ static void team_port_leave(struct team *team, struct team_port *port) } #ifdef CONFIG_NET_POLL_CONTROLLER -static int __team_port_enable_netpoll(struct team_port *port) +static int team_port_enable_netpoll(struct team *team, struct team_port *port) { struct netpoll *np; int err; + if (!team->dev->npinfo) + return 0; + np = kzalloc(sizeof(*np), GFP_KERNEL); if (!np) return -ENOMEM; @@ -1069,14 +1055,6 @@ static int __team_port_enable_netpoll(struct team_port *port) return err; } -static int team_port_enable_netpoll(struct team_port *port) -{ - if (!port->team->dev->npinfo) - return 0; - - return __team_port_enable_netpoll(port); -} - static void team_port_disable_netpoll(struct team_port *port) { struct netpoll *np = port->np; @@ -1091,7 +1069,7 @@ static void team_port_disable_netpoll(struct team_port *port) kfree(np); } #else -static int team_port_enable_netpoll(struct team_port *port) +static int team_port_enable_netpoll(struct team *team, struct team_port *port) { return 0; } @@ -1198,7 +1176,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) goto err_vids_add; } - err = team_port_enable_netpoll(port); + err = team_port_enable_netpoll(team, port); if (err) { netdev_err(dev, "Failed to enable netpoll on device %s\n", portname); @@ -1906,7 +1884,7 @@ static int team_netpoll_setup(struct net_device *dev, mutex_lock(&team->lock); list_for_each_entry(port, &team->port_list, list) { - err = __team_port_enable_netpoll(port); + err = team_port_enable_netpoll(team, port); if (err) { __team_netpoll_cleanup(team); break; @@ -2360,10 +2338,8 @@ static int team_nl_send_options_get(struct team *team, u32 portid, u32 seq, hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI, TEAM_CMD_OPTIONS_GET); - if (!hdr) { - nlmsg_free(skb); + if (!hdr) return -EMSGSIZE; - } if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; @@ -2397,7 +2373,7 @@ static int team_nl_send_options_get(struct team *team, u32 portid, u32 seq, if (!nlh) { err = __send_and_alloc_skb(&skb, team, portid, send_func); if (err) - return err; + goto errout; goto send_done; } @@ -2561,14 +2537,6 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) if (err) goto team_put; opt_inst->changed = true; - - /* dumb/evil user-space can send us duplicate opt, - * keep only the last one - */ - if (__team_option_inst_tmp_find(&opt_inst_list, - opt_inst)) - continue; - list_add(&opt_inst->tmp_list, &opt_inst_list); } if (!opt_found) { @@ -2638,10 +2606,8 @@ static int team_nl_send_port_list_get(struct team *team, u32 portid, u32 seq, hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI, TEAM_CMD_PORT_LIST_GET); - if (!hdr) { - nlmsg_free(skb); + if (!hdr) return -EMSGSIZE; - } if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; @@ -2685,7 +2651,7 @@ static int team_nl_send_port_list_get(struct team *team, u32 portid, u32 seq, if (!nlh) { err = __send_and_alloc_skb(&skb, team, portid, send_func); if (err) - return err; + goto errout; goto send_done; } diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 5225eb40f6b5..6a2df3d96fd6 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -600,13 +600,11 @@ static void tun_detach_all(struct net_device *dev) for (i = 0; i < n; i++) { tfile = rtnl_dereference(tun->tfiles[i]); BUG_ON(!tfile); - tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN; tfile->socket.sk->sk_data_ready(tfile->socket.sk); RCU_INIT_POINTER(tfile->tun, NULL); --tun->numqueues; } list_for_each_entry(tfile, &tun->disabled, next) { - tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN; tfile->socket.sk->sk_data_ready(tfile->socket.sk); RCU_INIT_POINTER(tfile->tun, NULL); } @@ -662,7 +660,6 @@ static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filte goto out; } tfile->queue_index = tun->numqueues; - tfile->socket.sk->sk_shutdown &= ~RCV_SHUTDOWN; rcu_assign_pointer(tfile->tun, tun); rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile); tun->numqueues++; @@ -1141,11 +1138,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, } if (tun->flags & IFF_VNET_HDR) { - int vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz); - - if (len < vnet_hdr_sz) + if (len < tun->vnet_hdr_sz) return -EINVAL; - len -= vnet_hdr_sz; + len -= tun->vnet_hdr_sz; n = copy_from_iter(&gso, sizeof(gso), from); if (n != sizeof(gso)) @@ -1157,7 +1152,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, if (tun16_to_cpu(tun, gso.hdr_len) > len) return -EINVAL; - iov_iter_advance(from, vnet_hdr_sz - sizeof(gso)); + iov_iter_advance(from, tun->vnet_hdr_sz - sizeof(gso)); } if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP) { @@ -1228,13 +1223,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, switch (tun->flags & TUN_TYPE_MASK) { case IFF_TUN: if (tun->flags & IFF_NO_PI) { - u8 ip_version = skb->len ? (skb->data[0] >> 4) : 0; - - switch (ip_version) { - case 4: + switch (skb->data[0] & 0xf0) { + case 0x40: pi.proto = htons(ETH_P_IP); break; - case 6: + case 0x60: pi.proto = htons(ETH_P_IPV6); break; default: @@ -1378,7 +1371,7 @@ static ssize_t tun_put_user(struct tun_struct *tun, vlan_hlen = VLAN_HLEN; if (tun->flags & IFF_VNET_HDR) - vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz); + vnet_hdr_sz = tun->vnet_hdr_sz; total = skb->len + vlan_hlen + vnet_hdr_sz; @@ -1512,6 +1505,9 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile, if (!iov_iter_count(to)) return 0; + if (tun->dev->reg_state != NETREG_REGISTERED) + return -EIO; + /* Read frames from queue */ skb = __skb_recv_datagram(tfile->socket.sk, noblock ? MSG_DONTWAIT : 0, &peeked, &off, &err); @@ -1783,9 +1779,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) if (!dev) return -ENOMEM; - err = dev_get_valid_name(net, dev, name); - if (err < 0) - goto err_free_dev; dev_net_set(dev, net); dev->rtnl_link_ops = &tun_link_ops; @@ -2190,10 +2183,6 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ret = -EFAULT; break; } - if (sndbuf <= 0) { - ret = -EINVAL; - break; - } tun->sndbuf = sndbuf; tun_set_sndbuf(tun); diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 3a7286256db0..7f83504dfa69 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -364,7 +364,7 @@ config USB_NET_NET1080 optionally with LEDs that indicate traffic config USB_NET_PLUSB - tristate "Prolific PL-2301/2302/25A1/27A1 based cables" + tristate "Prolific PL-2301/2302/25A1 based cables" # if the handshake/init/reset problems, from original 'plusb', # are ever resolved ... then remove "experimental" depends on USB_USBNET @@ -395,10 +395,6 @@ config USB_NET_RNDIS_HOST The protocol specification is incomplete, and is controlled by (and for) Microsoft; it isn't an "Open" ecosystem or market. -config USB_NET_CDC_SUBSET_ENABLE - tristate - depends on USB_NET_CDC_SUBSET - config USB_NET_CDC_SUBSET tristate "Simple USB Network Links (CDC Ethernet subset)" depends on USB_USBNET @@ -417,7 +413,6 @@ config USB_NET_CDC_SUBSET config USB_ALI_M5632 bool "ALi M5632 based 'USB 2.0 Data Link' cables" depends on USB_NET_CDC_SUBSET - select USB_NET_CDC_SUBSET_ENABLE help Choose this option if you're using a host-to-host cable based on this design, which supports USB 2.0 high speed. @@ -425,7 +420,6 @@ config USB_ALI_M5632 config USB_AN2720 bool "AnchorChips 2720 based cables (Xircom PGUNET, ...)" depends on USB_NET_CDC_SUBSET - select USB_NET_CDC_SUBSET_ENABLE help Choose this option if you're using a host-to-host cable based on this design. Note that AnchorChips is now a @@ -434,7 +428,6 @@ config USB_AN2720 config USB_BELKIN bool "eTEK based host-to-host cables (Advance, Belkin, ...)" depends on USB_NET_CDC_SUBSET - select USB_NET_CDC_SUBSET_ENABLE default y help Choose this option if you're using a host-to-host cable @@ -444,7 +437,6 @@ config USB_BELKIN config USB_ARMLINUX bool "Embedded ARM Linux links (iPaq, ...)" depends on USB_NET_CDC_SUBSET - select USB_NET_CDC_SUBSET_ENABLE default y help Choose this option to support the "usb-eth" networking driver @@ -462,7 +454,6 @@ config USB_ARMLINUX config USB_EPSON2888 bool "Epson 2888 based firmware (DEVELOPMENT)" depends on USB_NET_CDC_SUBSET - select USB_NET_CDC_SUBSET_ENABLE help Choose this option to support the usb networking links used by some sample firmware from Epson. @@ -470,7 +461,6 @@ config USB_EPSON2888 config USB_KC2190 bool "KT Technology KC2190 based cables (InstaNet)" depends on USB_NET_CDC_SUBSET - select USB_NET_CDC_SUBSET_ENABLE help Choose this option if you're using a host-to-host cable with one of these chips. diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 37fb46aee341..b5f04068dbe4 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_USB_NET_GL620A) += gl620a.o obj-$(CONFIG_USB_NET_NET1080) += net1080.o obj-$(CONFIG_USB_NET_PLUSB) += plusb.o obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndis_host.o -obj-$(CONFIG_USB_NET_CDC_SUBSET_ENABLE) += cdc_subset.o +obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o obj-$(CONFIG_USB_USBNET) += usbnet.o diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 2aa1a1d29cb4..4e2b26a88b15 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -777,7 +777,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id struct net_device *netdev; struct catc *catc; u8 broadcast[ETH_ALEN]; - int pktsz, ret; + int i, pktsz; if (usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 1)) { @@ -812,8 +812,12 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id if ((!catc->ctrl_urb) || (!catc->tx_urb) || (!catc->rx_urb) || (!catc->irq_urb)) { dev_err(&intf->dev, "No free urbs available.\n"); - ret = -ENOMEM; - goto fail_free; + usb_free_urb(catc->ctrl_urb); + usb_free_urb(catc->tx_urb); + usb_free_urb(catc->rx_urb); + usb_free_urb(catc->irq_urb); + free_netdev(netdev); + return -ENOMEM; } /* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */ @@ -841,24 +845,15 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id catc->irq_buf, 2, catc_irq_done, catc, 1); if (!catc->is_f5u011) { - u32 *buf; - int i; - dev_dbg(dev, "Checking memory size\n"); - buf = kmalloc(4, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto fail_free; - } - - *buf = 0x12345678; - catc_write_mem(catc, 0x7a80, buf, 4); - *buf = 0x87654321; - catc_write_mem(catc, 0xfa80, buf, 4); - catc_read_mem(catc, 0x7a80, buf, 4); + i = 0x12345678; + catc_write_mem(catc, 0x7a80, &i, 4); + i = 0x87654321; + catc_write_mem(catc, 0xfa80, &i, 4); + catc_read_mem(catc, 0x7a80, &i, 4); - switch (*buf) { + switch (i) { case 0x12345678: catc_set_reg(catc, TxBufCount, 8); catc_set_reg(catc, RxBufCount, 32); @@ -873,8 +868,6 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id dev_dbg(dev, "32k Memory\n"); break; } - - kfree(buf); dev_dbg(dev, "Getting MAC from SEEROM.\n"); @@ -921,21 +914,16 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id usb_set_intfdata(intf, catc); SET_NETDEV_DEV(netdev, &intf->dev); - ret = register_netdev(netdev); - if (ret) - goto fail_clear_intfdata; - + if (register_netdev(netdev) != 0) { + usb_set_intfdata(intf, NULL); + usb_free_urb(catc->ctrl_urb); + usb_free_urb(catc->tx_urb); + usb_free_urb(catc->rx_urb); + usb_free_urb(catc->irq_urb); + free_netdev(netdev); + return -EIO; + } return 0; - -fail_clear_intfdata: - usb_set_intfdata(intf, NULL); -fail_free: - usb_free_urb(catc->ctrl_urb); - usb_free_urb(catc->tx_urb); - usb_free_urb(catc->rx_urb); - usb_free_urb(catc->irq_urb); - free_netdev(netdev); - return ret; } static void catc_disconnect(struct usb_interface *intf) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index f71abe50ea6f..7cba2c3759df 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -221,7 +221,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) goto bad_desc; } - if (header.usb_cdc_ether_desc && info->ether->wMaxSegmentSize) { + if (header.usb_cdc_ether_desc) { dev->hard_mtu = le16_to_cpu(info->ether->wMaxSegmentSize); /* because of Zaurus, we may be ignoring the host * side link address we were given. @@ -461,9 +461,7 @@ static const struct driver_info wwan_info = { #define REALTEK_VENDOR_ID 0x0bda #define SAMSUNG_VENDOR_ID 0x04e8 #define LENOVO_VENDOR_ID 0x17ef -#define LINKSYS_VENDOR_ID 0x13b1 #define NVIDIA_VENDOR_ID 0x0955 -#define HP_VENDOR_ID 0x03f0 static const struct usb_device_id products[] = { /* BLACKLIST !! @@ -610,13 +608,6 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, -/* HP lt2523 (Novatel E371) - handled by qmi_wwan */ -{ - USB_DEVICE_AND_INTERFACE_INFO(HP_VENDOR_ID, 0x421d, USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), - .driver_info = 0, -}, - /* AnyDATA ADU960S - handled by qmi_wwan */ { USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a, USB_CLASS_COMM, @@ -651,15 +642,6 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, -#if IS_ENABLED(CONFIG_USB_RTL8152) -/* Linksys USB3GIGV1 Ethernet Adapter */ -{ - USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), - .driver_info = 0, -}, -#endif - /* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM, @@ -714,12 +696,6 @@ static const struct usb_device_id products[] = { USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&wwan_info, -}, { - /* Cinterion AHS3 modem by GEMALTO */ - USB_DEVICE_AND_INTERFACE_INFO(0x1e2d, 0x0055, USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, - USB_CDC_PROTO_NONE), - .driver_info = (unsigned long)&wwan_info, }, { /* Telit modules */ USB_VENDOR_AND_INTERFACE_INFO(0x1bc7, USB_CLASS_COMM, diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 8edbccf06b7b..96a5028621c8 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -593,7 +593,7 @@ static const struct driver_info cdc_mbim_info_zlp = { */ static const struct driver_info cdc_mbim_info_ndp_to_end = { .description = "CDC MBIM", - .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP, + .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN, .bind = cdc_mbim_bind, .unbind = cdc_mbim_unbind, .manage_power = cdc_mbim_manage_power, diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 5ce386028b91..b2268ebd0159 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -724,10 +724,8 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ u8 *buf; int len; int temp; - int err; u8 iface_no; struct usb_cdc_parsed_header hdr; - u16 curr_ntb_format; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -811,13 +809,6 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ if (cdc_ncm_init(dev)) goto error2; - /* Some firmwares need a pause here or they will silently fail - * to set up the interface properly. This value was decided - * empirically on a Sierra Wireless MC7455 running 02.08.02.00 - * firmware. - */ - usleep_range(10000, 20000); - /* configure data interface */ temp = usb_set_interface(dev->udev, iface_no, data_altsetting); if (temp) { @@ -825,35 +816,6 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ goto error2; } - /* Device-specific flags */ - ctx->drvflags = drvflags; - - /* - * Some Huawei devices have been observed to come out of reset in NDP32 mode. - * Let's check if this is the case, and set the device to NDP16 mode again if - * needed. - */ - if (ctx->drvflags & CDC_NCM_FLAG_RESET_NTB16) { - err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_FORMAT, - USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE, - 0, iface_no, &curr_ntb_format, 2); - if (err < 0) { - goto error2; - } - - if (curr_ntb_format == USB_CDC_NCM_NTB32_FORMAT) { - dev_info(&intf->dev, "resetting NTB format to 16-bit"); - err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT, - USB_TYPE_CLASS | USB_DIR_OUT - | USB_RECIP_INTERFACE, - USB_CDC_NCM_NTB16_FORMAT, - iface_no, NULL, 0); - - if (err < 0) - goto error2; - } - } - cdc_ncm_find_endpoints(dev, ctx->data); cdc_ncm_find_endpoints(dev, ctx->control); if (!dev->in || !dev->out || !dev->status) { @@ -876,6 +838,9 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ /* finish setting up the device specific data */ cdc_ncm_setup(dev); + /* Device-specific flags */ + ctx->drvflags = drvflags; + /* Allocate the delayed NDP if needed. */ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL); @@ -1069,13 +1034,12 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) u16 n = 0, index, ndplen; u8 ready2send = 0; u32 delayed_ndp_size; - size_t padding_count; /* When our NDP gets written in cdc_ncm_ndp(), then skb_out->len gets updated * accordingly. Otherwise, we should check here. */ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) - delayed_ndp_size = ALIGN(ctx->max_ndp_size, ctx->tx_ndp_modulus); + delayed_ndp_size = ctx->max_ndp_size; else delayed_ndp_size = 0; @@ -1208,7 +1172,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) /* If requested, put NDP at end of frame. */ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data; - cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_max - ctx->max_ndp_size); + cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_max); nth16->wNdpIndex = cpu_to_le16(skb_out->len); memcpy(skb_put(skb_out, ctx->max_ndp_size), ctx->delayed_ndp16, ctx->max_ndp_size); @@ -1226,13 +1190,11 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) * a ZLP after full sized NTBs. */ if (!(dev->driver_info->flags & FLAG_SEND_ZLP) && - skb_out->len > ctx->min_tx_pkt) { - padding_count = ctx->tx_max - skb_out->len; - memset(skb_put(skb_out, padding_count), 0, padding_count); - } else if (skb_out->len < ctx->tx_max && - (skb_out->len % dev->maxpacket) == 0) { + skb_out->len > ctx->min_tx_pkt) + memset(skb_put(skb_out, ctx->tx_max - skb_out->len), 0, + ctx->tx_max - skb_out->len); + else if (skb_out->len < ctx->tx_max && (skb_out->len % dev->maxpacket) == 0) *skb_put(skb_out, 1) = 0; /* force short packet */ - } /* set final frame length */ nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data; diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c index 947bea81d924..e221bfcee76b 100644 --- a/drivers/net/usb/cx82310_eth.c +++ b/drivers/net/usb/cx82310_eth.c @@ -293,9 +293,12 @@ static struct sk_buff *cx82310_tx_fixup(struct usbnet *dev, struct sk_buff *skb, { int len = skb->len; - if (skb_cow_head(skb, 2)) { + if (skb_headroom(skb) < 2) { + struct sk_buff *skb2 = skb_copy_expand(skb, 2, 0, flags); dev_kfree_skb_any(skb); - return NULL; + skb = skb2; + if (!skb) + return NULL; } skb_push(skb, 2); diff --git a/drivers/net/usb/huawei_cdc_ncm.c b/drivers/net/usb/huawei_cdc_ncm.c index 63f28908afda..2680a65cd5e4 100644 --- a/drivers/net/usb/huawei_cdc_ncm.c +++ b/drivers/net/usb/huawei_cdc_ncm.c @@ -80,12 +80,6 @@ static int huawei_cdc_ncm_bind(struct usbnet *usbnet_dev, * be at the end of the frame. */ drvflags |= CDC_NCM_FLAG_NDP_TO_END; - - /* Additionally, it has been reported that some Huawei E3372H devices, with - * firmware version 21.318.01.00.541, come out of reset in NTB32 format mode, hence - * needing to be set to the NTB16 one again. - */ - drvflags |= CDC_NCM_FLAG_RESET_NTB16; ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags); if (ret) goto err; diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index cd93220c9b45..f64b25c221e8 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -1009,7 +1009,6 @@ static int kaweth_probe( struct net_device *netdev; const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; int result = 0; - int rv = -EIO; dev_dbg(dev, "Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x\n", @@ -1030,7 +1029,6 @@ static int kaweth_probe( kaweth = netdev_priv(netdev); kaweth->dev = udev; kaweth->net = netdev; - kaweth->intf = intf; spin_lock_init(&kaweth->device_lock); init_waitqueue_head(&kaweth->term_wait); @@ -1050,10 +1048,6 @@ static int kaweth_probe( /* Download the firmware */ dev_info(dev, "Downloading firmware...\n"); kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL); - if (!kaweth->firmware_buf) { - rv = -ENOMEM; - goto err_free_netdev; - } if ((result = kaweth_download_firmware(kaweth, "kaweth/new_code.bin", 100, @@ -1145,6 +1139,8 @@ static int kaweth_probe( dev_dbg(dev, "Initializing net device.\n"); + kaweth->intf = intf; + kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->tx_urb) goto err_free_netdev; @@ -1208,7 +1204,7 @@ static int kaweth_probe( err_free_netdev: free_netdev(netdev); - return rv; + return -EIO; } /**************************************************************** diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index acec4b565511..d7d986971bac 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -618,8 +618,7 @@ static int lan78xx_read_otp(struct lan78xx_net *dev, u32 offset, offset += 0x100; else ret = -EINVAL; - if (!ret) - ret = lan78xx_read_raw_otp(dev, offset, length, data); + ret = lan78xx_read_raw_otp(dev, offset, length, data); } return ret; @@ -1862,7 +1861,6 @@ static int lan78xx_reset(struct lan78xx_net *dev) buf = DEFAULT_BURST_CAP_SIZE / FS_USB_PKT_SIZE; dev->rx_urb_size = DEFAULT_BURST_CAP_SIZE; dev->rx_qlen = 4; - dev->tx_qlen = 4; } ret = lan78xx_write_reg(dev, BURST_CAP, buf); @@ -2054,9 +2052,14 @@ static struct sk_buff *lan78xx_tx_prep(struct lan78xx_net *dev, { u32 tx_cmd_a, tx_cmd_b; - if (skb_cow_head(skb, TX_OVERHEAD)) { + if (skb_headroom(skb) < TX_OVERHEAD) { + struct sk_buff *skb2; + + skb2 = skb_copy_expand(skb, TX_OVERHEAD, 0, flags); dev_kfree_skb_any(skb); - return NULL; + skb = skb2; + if (!skb) + return NULL; } if (lan78xx_linearize(skb) < 0) diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 17fac0121e56..f84080215915 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -126,61 +126,40 @@ static void async_ctrl_callback(struct urb *urb) static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) { - u8 *buf; int ret; - buf = kmalloc(size, GFP_NOIO); - if (!buf) - return -ENOMEM; - ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0), PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0, - indx, buf, size, 1000); + indx, data, size, 1000); if (ret < 0) netif_dbg(pegasus, drv, pegasus->net, "%s returned %d\n", __func__, ret); - else if (ret <= size) - memcpy(data, buf, ret); - kfree(buf); return ret; } -static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, - const void *data) +static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) { - u8 *buf; int ret; - buf = kmemdup(data, size, GFP_NOIO); - if (!buf) - return -ENOMEM; - ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0, - indx, buf, size, 100); + indx, data, size, 100); if (ret < 0) netif_dbg(pegasus, drv, pegasus->net, "%s returned %d\n", __func__, ret); - kfree(buf); return ret; } static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data) { - u8 *buf; int ret; - buf = kmemdup(&data, 1, GFP_NOIO); - if (!buf) - return -ENOMEM; - ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data, - indx, buf, 1, 1000); + indx, &data, 1, 1000); if (ret < 0) netif_dbg(pegasus, drv, pegasus->net, "%s returned %d\n", __func__, ret); - kfree(buf); return ret; } diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c index 7c02231c1a1b..1bfe0fcaccf5 100644 --- a/drivers/net/usb/plusb.c +++ b/drivers/net/usb/plusb.c @@ -102,7 +102,7 @@ static int pl_reset(struct usbnet *dev) } static const struct driver_info prolific_info = { - .description = "Prolific PL-2301/PL-2302/PL-25A1/PL-27A1", + .description = "Prolific PL-2301/PL-2302/PL-25A1", .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT, /* some PL-2302 versions seem to fail usb_set_interface() */ .reset = pl_reset, @@ -139,17 +139,6 @@ static const struct usb_device_id products [] = { * Host-to-Host Cable */ .driver_info = (unsigned long) &prolific_info, - -}, - -/* super speed cables */ -{ - USB_DEVICE(0x067b, 0x27a1), /* PL-27A1, no eeprom - * also: goobay Active USB 3.0 - * Data Link, - * Unitek Y-3501 - */ - .driver_info = (unsigned long) &prolific_info, }, { }, // END @@ -169,5 +158,5 @@ static struct usb_driver plusb_driver = { module_usb_driver(plusb_driver); MODULE_AUTHOR("David Brownell"); -MODULE_DESCRIPTION("Prolific PL-2301/2302/25A1/27A1 USB Host to Host Link Driver"); +MODULE_DESCRIPTION("Prolific PL-2301/2302/25A1 USB Host to Host Link Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 3b67140eed73..a34f491224c1 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -262,7 +262,7 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) } /* errors aren't fatal - we can live with the dynamic address */ - if (cdc_ether && cdc_ether->wMaxSegmentSize) { + if (cdc_ether) { dev->hard_mtu = le16_to_cpu(cdc_ether->wMaxSegmentSize); usbnet_get_ethernet_addr(dev, cdc_ether->iMACAddress); } @@ -410,10 +410,6 @@ static const struct usb_device_id products[] = { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x69), .driver_info = (unsigned long)&qmi_wwan_info, }, - { /* Motorola Mapphone devices with MDM6600 */ - USB_VENDOR_AND_INTERFACE_INFO(0x22b8, USB_CLASS_VENDOR_SPEC, 0xfb, 0xff), - .driver_info = (unsigned long)&qmi_wwan_info, - }, /* 2. Combined interface devices matching on class+protocol */ { /* Huawei E367 and possibly others in "Windows mode" */ @@ -489,13 +485,6 @@ static const struct usb_device_id products[] = { USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&qmi_wwan_info, }, - { /* HP lt2523 (Novatel E371) */ - USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d, - USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, - USB_CDC_PROTO_NONE), - .driver_info = (unsigned long)&qmi_wwan_info, - }, { /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */ USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7), .driver_info = (unsigned long)&qmi_wwan_info, @@ -631,16 +620,11 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x05c6, 0x9080, 8)}, {QMI_FIXED_INTF(0x05c6, 0x9083, 3)}, {QMI_FIXED_INTF(0x05c6, 0x9084, 4)}, - {QMI_FIXED_INTF(0x05c6, 0x90b2, 3)}, /* ublox R410M */ {QMI_FIXED_INTF(0x05c6, 0x920d, 0)}, {QMI_FIXED_INTF(0x05c6, 0x920d, 5)}, {QMI_FIXED_INTF(0x0846, 0x68a2, 8)}, - {QMI_FIXED_INTF(0x0846, 0x68d3, 8)}, /* Netgear Aircard 779S */ {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */ {QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */ - {QMI_FIXED_INTF(0x1435, 0xd181, 3)}, /* Wistron NeWeb D18Q1 */ - {QMI_FIXED_INTF(0x1435, 0xd181, 4)}, /* Wistron NeWeb D18Q1 */ - {QMI_FIXED_INTF(0x1435, 0xd181, 5)}, /* Wistron NeWeb D18Q1 */ {QMI_FIXED_INTF(0x16d8, 0x6003, 0)}, /* CMOTech 6003 */ {QMI_FIXED_INTF(0x16d8, 0x6007, 0)}, /* CMOTech CHE-628S */ {QMI_FIXED_INTF(0x16d8, 0x6008, 0)}, /* CMOTech CMU-301 */ @@ -716,8 +700,6 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x19d2, 0x1428, 2)}, /* Telewell TW-LTE 4G v2 */ {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ {QMI_FIXED_INTF(0x2001, 0x7e19, 4)}, /* D-Link DWM-221 B1 */ - {QMI_FIXED_INTF(0x2001, 0x7e35, 4)}, /* D-Link DWM-222 */ - {QMI_FIXED_INTF(0x2020, 0x2033, 4)}, /* BroadMobi BM806U */ {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ @@ -741,9 +723,6 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx */ {QMI_FIXED_INTF(0x1199, 0x9079, 8)}, /* Sierra Wireless EM74xx */ {QMI_FIXED_INTF(0x1199, 0x9079, 10)}, /* Sierra Wireless EM74xx */ - {QMI_FIXED_INTF(0x1199, 0x907b, 8)}, /* Sierra Wireless EM74xx */ - {QMI_FIXED_INTF(0x1199, 0x907b, 10)}, /* Sierra Wireless EM74xx */ - {QMI_FIXED_INTF(0x1199, 0x9091, 8)}, /* Sierra Wireless EM7565 */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */ {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ @@ -767,9 +746,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ {QMI_FIXED_INTF(0x413c, 0x81b1, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */ {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ - {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */ {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ - {QMI_FIXED_INTF(0x1e0e, 0x9001, 5)}, /* SIMCom 7230E */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ @@ -861,18 +838,6 @@ static int qmi_wwan_probe(struct usb_interface *intf, id->driver_info = (unsigned long)&qmi_wwan_info; } - /* There are devices where the same interface number can be - * configured as different functions. We should only bind to - * vendor specific functions when matching on interface number - */ - if (id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER && - desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) { - dev_dbg(&intf->dev, - "Rejecting interface number match for class %02x\n", - desc->bInterfaceClass); - return -ENODEV; - } - /* Quectel EC20 quirk where we've QMI on interface 4 instead of 0 */ if (quectel_ec20_detected(intf) && desc->bInterfaceNumber == 0) { dev_dbg(&intf->dev, "Quectel EC20 quirk, skipping interface 0\n"); diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 2bb336cb13ee..2fb637ad594a 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -25,13 +25,12 @@ #include #include #include -#include /* Information for net-next */ #define NETNEXT_VERSION "08" /* Information for net */ -#define NET_VERSION "3" +#define NET_VERSION "2" #define DRIVER_VERSION "v1." NETNEXT_VERSION "." NET_VERSION #define DRIVER_AUTHOR "Realtek linux nic maintainers " @@ -506,7 +505,6 @@ enum rtl8152_flags { #define VENDOR_ID_REALTEK 0x0bda #define VENDOR_ID_SAMSUNG 0x04e8 #define VENDOR_ID_LENOVO 0x17ef -#define VENDOR_ID_LINKSYS 0x13b1 #define VENDOR_ID_NVIDIA 0x0955 #define MCU_TYPE_PLA 0x0100 @@ -606,9 +604,6 @@ struct r8152 { struct delayed_work schedule; struct mii_if_info mii; struct mutex control; /* use for hw setting */ -#ifdef CONFIG_PM_SLEEP - struct notifier_block pm_notifier; -#endif struct rtl_ops { void (*init)(struct r8152 *); @@ -1212,7 +1207,6 @@ static void intr_callback(struct urb *urb) } } else { if (netif_carrier_ok(tp->netdev)) { - netif_stop_queue(tp->netdev); set_bit(RTL8152_LINK_CHG, &tp->flags); schedule_delayed_work(&tp->schedule, 0); } @@ -1283,7 +1277,6 @@ static int alloc_all_mem(struct r8152 *tp) spin_lock_init(&tp->rx_lock); spin_lock_init(&tp->tx_lock); INIT_LIST_HEAD(&tp->tx_free); - INIT_LIST_HEAD(&tp->rx_done); skb_queue_head_init(&tp->tx_queue); skb_queue_head_init(&tp->rx_queue); @@ -1610,7 +1603,7 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) tx_data += len; agg->skb_len += len; - agg->skb_num += skb_shinfo(skb)->gso_segs ?: 1; + agg->skb_num++; dev_kfree_skb_any(skb); @@ -1652,7 +1645,7 @@ static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc) u8 checksum = CHECKSUM_NONE; u32 opts2, opts3; - if (!(tp->netdev->features & NETIF_F_RXCSUM)) + if (tp->version == RTL_VER_01) goto return_result; opts2 = le32_to_cpu(rx_desc->opts2); @@ -1858,9 +1851,6 @@ static int r8152_poll(struct napi_struct *napi, int budget) napi_complete(napi); if (!list_empty(&tp->rx_done)) napi_schedule(napi); - else if (!skb_queue_empty(&tp->tx_queue) && - !list_empty(&tp->tx_free)) - napi_schedule(napi); } return work_done; @@ -1948,6 +1938,7 @@ static void _rtl8152_set_rx_mode(struct net_device *netdev) __le32 tmp[2]; u32 ocp_data; + clear_bit(RTL8152_SET_RX_MODE, &tp->flags); netif_stop_queue(netdev); ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); ocp_data &= ~RCR_ACPT_ALL; @@ -2433,6 +2424,8 @@ static void rtl_phy_reset(struct r8152 *tp) u16 data; int i; + clear_bit(PHY_RESET, &tp->flags); + data = r8152_mdio_read(tp, MII_BMCR); /* don't reset again before the previous one complete */ @@ -2462,23 +2455,23 @@ static void r8153_teredo_off(struct r8152 *tp) ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TEREDO_TIMER, 0); } -static void r8152_aldps_en(struct r8152 *tp, bool enable) +static void r8152b_disable_aldps(struct r8152 *tp) { - if (enable) { - ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS | - LINKENA | DIS_SDSAVE); - } else { - ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | - DIS_SDSAVE); - msleep(20); - } + ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE); + msleep(20); +} + +static inline void r8152b_enable_aldps(struct r8152 *tp) +{ + ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS | + LINKENA | DIS_SDSAVE); } static void rtl8152_disable(struct r8152 *tp) { - r8152_aldps_en(tp, false); + r8152b_disable_aldps(tp); rtl_disable(tp); - r8152_aldps_en(tp, true); + r8152b_enable_aldps(tp); } static void r8152b_hw_phy_cfg(struct r8152 *tp) @@ -2790,26 +2783,30 @@ static void r8153_enter_oob(struct r8152 *tp) ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); } -static void r8153_aldps_en(struct r8152 *tp, bool enable) +static void r8153_disable_aldps(struct r8152 *tp) { u16 data; data = ocp_reg_read(tp, OCP_POWER_CFG); - if (enable) { - data |= EN_ALDPS; - ocp_reg_write(tp, OCP_POWER_CFG, data); - } else { - data &= ~EN_ALDPS; - ocp_reg_write(tp, OCP_POWER_CFG, data); - msleep(20); - } + data &= ~EN_ALDPS; + ocp_reg_write(tp, OCP_POWER_CFG, data); + msleep(20); +} + +static void r8153_enable_aldps(struct r8152 *tp) +{ + u16 data; + + data = ocp_reg_read(tp, OCP_POWER_CFG); + data |= EN_ALDPS; + ocp_reg_write(tp, OCP_POWER_CFG, data); } static void rtl8153_disable(struct r8152 *tp) { - r8153_aldps_en(tp, false); + r8153_disable_aldps(tp); rtl_disable(tp); - r8153_aldps_en(tp, true); + r8153_enable_aldps(tp); usb_enable_lpm(tp->udev); } @@ -2887,9 +2884,10 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex) r8152_mdio_write(tp, MII_ADVERTISE, anar); r8152_mdio_write(tp, MII_BMCR, bmcr); - if (test_and_clear_bit(PHY_RESET, &tp->flags)) { + if (test_bit(PHY_RESET, &tp->flags)) { int i; + clear_bit(PHY_RESET, &tp->flags); for (i = 0; i < 50; i++) { msleep(20); if ((r8152_mdio_read(tp, MII_BMCR) & BMCR_RESET) == 0) @@ -2898,6 +2896,7 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex) } out: + return ret; } @@ -2906,9 +2905,9 @@ static void rtl8152_up(struct r8152 *tp) if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; - r8152_aldps_en(tp, false); + r8152b_disable_aldps(tp); r8152b_exit_oob(tp); - r8152_aldps_en(tp, true); + r8152b_enable_aldps(tp); } static void rtl8152_down(struct r8152 *tp) @@ -2919,9 +2918,9 @@ static void rtl8152_down(struct r8152 *tp) } r8152_power_cut_en(tp, false); - r8152_aldps_en(tp, false); + r8152b_disable_aldps(tp); r8152b_enter_oob(tp); - r8152_aldps_en(tp, true); + r8152b_enable_aldps(tp); } static void rtl8153_up(struct r8152 *tp) @@ -2930,9 +2929,9 @@ static void rtl8153_up(struct r8152 *tp) return; r8153_u1u2en(tp, false); - r8153_aldps_en(tp, false); + r8153_disable_aldps(tp); r8153_first_init(tp); - r8153_aldps_en(tp, true); + r8153_enable_aldps(tp); r8153_u2p3en(tp, true); r8153_u1u2en(tp, true); usb_enable_lpm(tp->udev); @@ -2948,9 +2947,9 @@ static void rtl8153_down(struct r8152 *tp) r8153_u1u2en(tp, false); r8153_u2p3en(tp, false); r8153_power_cut_en(tp, false); - r8153_aldps_en(tp, false); + r8153_disable_aldps(tp); r8153_enter_oob(tp); - r8153_aldps_en(tp, true); + r8153_enable_aldps(tp); } static bool rtl8152_in_nway(struct r8152 *tp) @@ -2984,22 +2983,17 @@ static void set_carrier(struct r8152 *tp) struct net_device *netdev = tp->netdev; u8 speed; + clear_bit(RTL8152_LINK_CHG, &tp->flags); speed = rtl8152_get_speed(tp); if (speed & LINK_STATUS) { if (!netif_carrier_ok(netdev)) { tp->rtl_ops.enable(tp); set_bit(RTL8152_SET_RX_MODE, &tp->flags); - netif_stop_queue(netdev); napi_disable(&tp->napi); netif_carrier_on(netdev); rtl_start_rx(tp); napi_enable(&tp->napi); - netif_wake_queue(netdev); - netif_info(tp, link, netdev, "carrier on\n"); - } else if (netif_queue_stopped(netdev) && - skb_queue_len(&tp->tx_queue) < tp->tx_qlen) { - netif_wake_queue(netdev); } } else { if (netif_carrier_ok(netdev)) { @@ -3007,7 +3001,6 @@ static void set_carrier(struct r8152 *tp) napi_disable(&tp->napi); tp->rtl_ops.disable(tp); napi_enable(&tp->napi); - netif_info(tp, link, netdev, "carrier off\n"); } } } @@ -3033,18 +3026,20 @@ static void rtl_work_func_t(struct work_struct *work) goto out1; } - if (test_and_clear_bit(RTL8152_LINK_CHG, &tp->flags)) + if (test_bit(RTL8152_LINK_CHG, &tp->flags)) set_carrier(tp); - if (test_and_clear_bit(RTL8152_SET_RX_MODE, &tp->flags)) + if (test_bit(RTL8152_SET_RX_MODE, &tp->flags)) _rtl8152_set_rx_mode(tp->netdev); /* don't schedule napi before linking */ - if (test_and_clear_bit(SCHEDULE_NAPI, &tp->flags) && - netif_carrier_ok(tp->netdev)) + if (test_bit(SCHEDULE_NAPI, &tp->flags) && + netif_carrier_ok(tp->netdev)) { + clear_bit(SCHEDULE_NAPI, &tp->flags); napi_schedule(&tp->napi); + } - if (test_and_clear_bit(PHY_RESET, &tp->flags)) + if (test_bit(PHY_RESET, &tp->flags)) rtl_phy_reset(tp); mutex_unlock(&tp->control); @@ -3053,33 +3048,6 @@ static void rtl_work_func_t(struct work_struct *work) usb_autopm_put_interface(tp->intf); } -#ifdef CONFIG_PM_SLEEP -static int rtl_notifier(struct notifier_block *nb, unsigned long action, - void *data) -{ - struct r8152 *tp = container_of(nb, struct r8152, pm_notifier); - - switch (action) { - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: - usb_autopm_get_interface(tp->intf); - break; - - case PM_POST_HIBERNATION: - case PM_POST_SUSPEND: - usb_autopm_put_interface(tp->intf); - break; - - case PM_POST_RESTORE: - case PM_RESTORE_PREPARE: - default: - break; - } - - return NOTIFY_DONE; -} -#endif - static int rtl8152_open(struct net_device *netdev) { struct r8152 *tp = netdev_priv(netdev); @@ -3122,10 +3090,6 @@ static int rtl8152_open(struct net_device *netdev) mutex_unlock(&tp->control); usb_autopm_put_interface(tp->intf); -#ifdef CONFIG_PM_SLEEP - tp->pm_notifier.notifier_call = rtl_notifier; - register_pm_notifier(&tp->pm_notifier); -#endif out: return res; @@ -3136,11 +3100,7 @@ static int rtl8152_close(struct net_device *netdev) struct r8152 *tp = netdev_priv(netdev); int res = 0; -#ifdef CONFIG_PM_SLEEP - unregister_pm_notifier(&tp->pm_notifier); -#endif - if (!test_bit(RTL8152_UNPLUG, &tp->flags)) - napi_disable(&tp->napi); + napi_disable(&tp->napi); clear_bit(WORK_ENABLE, &tp->flags); usb_kill_urb(tp->intr_urb); cancel_delayed_work_sync(&tp->schedule); @@ -3278,7 +3238,7 @@ static void r8152b_init(struct r8152 *tp) if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; - r8152_aldps_en(tp, false); + r8152b_disable_aldps(tp); if (tp->version == RTL_VER_01) { ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE); @@ -3300,7 +3260,7 @@ static void r8152b_init(struct r8152 *tp) ocp_write_word(tp, MCU_TYPE_PLA, PLA_GPHY_INTR_IMR, ocp_data); r8152b_enable_eee(tp); - r8152_aldps_en(tp, true); + r8152b_enable_aldps(tp); r8152b_enable_fc(tp); rtl_tally_reset(tp); @@ -3318,7 +3278,7 @@ static void r8153_init(struct r8152 *tp) if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; - r8153_aldps_en(tp, false); + r8153_disable_aldps(tp); r8153_u1u2en(tp, false); for (i = 0; i < 500; i++) { @@ -3407,7 +3367,7 @@ static void r8153_init(struct r8152 *tp) EEE_SPDWN_EN); r8153_enable_eee(tp); - r8153_aldps_en(tp, true); + r8153_enable_aldps(tp); r8152b_enable_fc(tp); rtl_tally_reset(tp); r8153_u2p3en(tp, true); @@ -3425,12 +3385,12 @@ static int rtl8152_pre_reset(struct usb_interface *intf) if (!netif_running(netdev)) return 0; - netif_stop_queue(netdev); napi_disable(&tp->napi); clear_bit(WORK_ENABLE, &tp->flags); usb_kill_urb(tp->intr_urb); cancel_delayed_work_sync(&tp->schedule); if (netif_carrier_ok(netdev)) { + netif_stop_queue(netdev); mutex_lock(&tp->control); tp->rtl_ops.disable(tp); mutex_unlock(&tp->control); @@ -3455,14 +3415,12 @@ static int rtl8152_post_reset(struct usb_interface *intf) if (netif_carrier_ok(netdev)) { mutex_lock(&tp->control); tp->rtl_ops.enable(tp); - rtl_start_rx(tp); rtl8152_set_rx_mode(netdev); mutex_unlock(&tp->control); + netif_wake_queue(netdev); } napi_enable(&tp->napi); - netif_wake_queue(netdev); - usb_submit_urb(tp->intr_urb, GFP_KERNEL); return 0; } @@ -3484,93 +3442,43 @@ static bool delay_autosuspend(struct r8152 *tp) */ if (!sw_linking && tp->rtl_ops.in_nway(tp)) return true; - else if (!skb_queue_empty(&tp->tx_queue)) - return true; else return false; } -static int rtl8152_rumtime_suspend(struct r8152 *tp) +static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message) { + struct r8152 *tp = usb_get_intfdata(intf); struct net_device *netdev = tp->netdev; int ret = 0; - if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) { - u32 rcr = 0; + mutex_lock(&tp->control); - if (delay_autosuspend(tp)) { + if (PMSG_IS_AUTO(message)) { + if (netif_running(netdev) && delay_autosuspend(tp)) { ret = -EBUSY; goto out1; } - if (netif_carrier_ok(netdev)) { - u32 ocp_data; - - rcr = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); - ocp_data = rcr & ~RCR_ACPT_ALL; - ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); - rxdy_gated_en(tp, true); - ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, - PLA_OOB_CTRL); - if (!(ocp_data & RXFIFO_EMPTY)) { - rxdy_gated_en(tp, false); - ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr); - ret = -EBUSY; - goto out1; - } - } - - clear_bit(WORK_ENABLE, &tp->flags); - usb_kill_urb(tp->intr_urb); - - rtl_runtime_suspend_enable(tp, true); - - if (netif_carrier_ok(netdev)) { - napi_disable(&tp->napi); - rtl_stop_rx(tp); - rxdy_gated_en(tp, false); - ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr); - napi_enable(&tp->napi); - } + set_bit(SELECTIVE_SUSPEND, &tp->flags); + } else { + netif_device_detach(netdev); } - set_bit(SELECTIVE_SUSPEND, &tp->flags); - -out1: - return ret; -} - -static int rtl8152_system_suspend(struct r8152 *tp) -{ - struct net_device *netdev = tp->netdev; - int ret = 0; - - netif_device_detach(netdev); - if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) { clear_bit(WORK_ENABLE, &tp->flags); usb_kill_urb(tp->intr_urb); napi_disable(&tp->napi); - cancel_delayed_work_sync(&tp->schedule); - tp->rtl_ops.down(tp); + if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { + rtl_stop_rx(tp); + rtl_runtime_suspend_enable(tp, true); + } else { + cancel_delayed_work_sync(&tp->schedule); + tp->rtl_ops.down(tp); + } napi_enable(&tp->napi); } - - return ret; -} - -static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct r8152 *tp = usb_get_intfdata(intf); - int ret; - - mutex_lock(&tp->control); - - if (PMSG_IS_AUTO(message)) - ret = rtl8152_rumtime_suspend(tp); - else - ret = rtl8152_system_suspend(tp); - +out1: mutex_unlock(&tp->control); return ret; @@ -3593,18 +3501,8 @@ static int rtl8152_resume(struct usb_interface *intf) clear_bit(SELECTIVE_SUSPEND, &tp->flags); napi_disable(&tp->napi); set_bit(WORK_ENABLE, &tp->flags); - - if (netif_carrier_ok(tp->netdev)) { - if (rtl8152_get_speed(tp) & LINK_STATUS) { - rtl_start_rx(tp); - } else { - netif_carrier_off(tp->netdev); - tp->rtl_ops.disable(tp); - netif_info(tp, link, tp->netdev, - "linking down\n"); - } - } - + if (netif_carrier_ok(tp->netdev)) + rtl_start_rx(tp); napi_enable(&tp->napi); } else { tp->rtl_ops.up(tp); @@ -4275,11 +4173,6 @@ static int rtl8152_probe(struct usb_interface *intf, NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | NETIF_F_IPV6_CSUM | NETIF_F_TSO6; - if (tp->version == RTL_VER_01) { - netdev->features &= ~NETIF_F_RXCSUM; - netdev->hw_features &= ~NETIF_F_RXCSUM; - } - netdev->ethtool_ops = &ops; netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE); @@ -4378,7 +4271,6 @@ static struct usb_device_id rtl8152_table[] = { {REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)}, - {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)}, {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)}, {} }; diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 58b1e18fdd64..d37b7dce2d40 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -155,36 +155,16 @@ static const char driver_name [] = "rtl8150"; */ static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) { - void *buf; - int ret; - - buf = kmalloc(size, GFP_NOIO); - if (!buf) - return -ENOMEM; - - ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), - RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, - indx, 0, buf, size, 500); - if (ret > 0 && ret <= size) - memcpy(data, buf, ret); - kfree(buf); - return ret; + return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), + RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, + indx, 0, data, size, 500); } -static int set_registers(rtl8150_t * dev, u16 indx, u16 size, const void *data) +static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) { - void *buf; - int ret; - - buf = kmemdup(data, size, GFP_NOIO); - if (!buf) - return -ENOMEM; - - ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), - RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, - indx, 0, buf, size, 500); - kfree(buf); - return ret; + return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), + RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, + indx, 0, data, size, 500); } static void async_set_reg_cb(struct urb *urb) @@ -681,7 +661,7 @@ static void rtl8150_set_multicast(struct net_device *netdev) (netdev->flags & IFF_ALLMULTI)) { rx_creg &= 0xfffe; rx_creg |= 0x0002; - dev_dbg(&netdev->dev, "%s: allmulti set\n", netdev->name); + dev_info(&netdev->dev, "%s: allmulti set\n", netdev->name); } else { /* ~RX_MULTICAST, ~RX_PROMISCUOUS */ rx_creg &= 0x00fc; diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index 0b5a84c9022c..a251588762ec 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -73,6 +73,8 @@ static atomic_t iface_counter = ATOMIC_INIT(0); /* Private data structure */ struct sierra_net_data { + u8 ethr_hdr_tmpl[ETH_HLEN]; /* ethernet header template for rx'd pkts */ + u16 link_up; /* air link up or down */ u8 tx_hdr_template[4]; /* part of HIP hdr for tx'd packets */ @@ -120,7 +122,6 @@ struct param { /* LSI Protocol types */ #define SIERRA_NET_PROTOCOL_UMTS 0x01 -#define SIERRA_NET_PROTOCOL_UMTS_DS 0x04 /* LSI Coverage */ #define SIERRA_NET_COVERAGE_NONE 0x00 #define SIERRA_NET_COVERAGE_NOPACKET 0x01 @@ -128,8 +129,7 @@ struct param { /* LSI Session */ #define SIERRA_NET_SESSION_IDLE 0x00 /* LSI Link types */ -#define SIERRA_NET_AS_LINK_TYPE_IPV4 0x00 -#define SIERRA_NET_AS_LINK_TYPE_IPV6 0x02 +#define SIERRA_NET_AS_LINK_TYPE_IPv4 0x00 struct lsi_umts { u8 protocol; @@ -137,14 +137,9 @@ struct lsi_umts { __be16 length; /* eventually use a union for the rest - assume umts for now */ u8 coverage; - u8 network_len; /* network name len */ - u8 network[40]; /* network name (UCS2, bigendian) */ + u8 unused2[41]; u8 session_state; u8 unused3[33]; -} __packed; - -struct lsi_umts_single { - struct lsi_umts lsi; u8 link_type; u8 pdp_addr_len; /* NW-supplied PDP address len */ u8 pdp_addr[16]; /* NW-supplied PDP address (bigendian)) */ @@ -163,31 +158,10 @@ struct lsi_umts_single { u8 reserved[8]; } __packed; -struct lsi_umts_dual { - struct lsi_umts lsi; - u8 pdp_addr4_len; /* NW-supplied PDP IPv4 address len */ - u8 pdp_addr4[4]; /* NW-supplied PDP IPv4 address (bigendian)) */ - u8 pdp_addr6_len; /* NW-supplied PDP IPv6 address len */ - u8 pdp_addr6[16]; /* NW-supplied PDP IPv6 address (bigendian)) */ - u8 unused4[23]; - u8 dns1_addr4_len; /* NW-supplied 1st DNS v4 address len (bigendian) */ - u8 dns1_addr4[4]; /* NW-supplied 1st DNS v4 address */ - u8 dns1_addr6_len; /* NW-supplied 1st DNS v6 address len */ - u8 dns1_addr6[16]; /* NW-supplied 1st DNS v6 address (bigendian)*/ - u8 dns2_addr4_len; /* NW-supplied 2nd DNS v4 address len (bigendian) */ - u8 dns2_addr4[4]; /* NW-supplied 2nd DNS v4 address */ - u8 dns2_addr6_len; /* NW-supplied 2nd DNS v6 address len */ - u8 dns2_addr6[16]; /* NW-supplied 2nd DNS v6 address (bigendian)*/ - u8 unused5[68]; -} __packed; - #define SIERRA_NET_LSI_COMMON_LEN 4 -#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts_single)) +#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts)) #define SIERRA_NET_LSI_UMTS_STATUS_LEN \ (SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN) -#define SIERRA_NET_LSI_UMTS_DS_LEN (sizeof(struct lsi_umts_dual)) -#define SIERRA_NET_LSI_UMTS_DS_STATUS_LEN \ - (SIERRA_NET_LSI_UMTS_DS_LEN - SIERRA_NET_LSI_COMMON_LEN) /* Forward definitions */ static void sierra_sync_timer(unsigned long syncdata); @@ -217,11 +191,10 @@ static inline void sierra_net_set_private(struct usbnet *dev, dev->data[0] = (unsigned long)priv; } -/* is packet IPv4/IPv6 */ +/* is packet IPv4 */ static inline int is_ip(struct sk_buff *skb) { - return skb->protocol == cpu_to_be16(ETH_P_IP) || - skb->protocol == cpu_to_be16(ETH_P_IPV6); + return skb->protocol == cpu_to_be16(ETH_P_IP); } /* @@ -377,54 +350,49 @@ static inline int sierra_net_is_valid_addrlen(u8 len) static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen) { struct lsi_umts *lsi = (struct lsi_umts *)data; - u32 expected_length; - if (datalen < sizeof(struct lsi_umts_single)) { - netdev_err(dev->net, "%s: Data length %d, exp >= %Zu\n", - __func__, datalen, sizeof(struct lsi_umts_single)); + if (datalen < sizeof(struct lsi_umts)) { + netdev_err(dev->net, "%s: Data length %d, exp %Zu\n", + __func__, datalen, + sizeof(struct lsi_umts)); return -1; } - /* Validate the session state */ - if (lsi->session_state == SIERRA_NET_SESSION_IDLE) { - netdev_err(dev->net, "Session idle, 0x%02x\n", - lsi->session_state); - return 0; + if (lsi->length != cpu_to_be16(SIERRA_NET_LSI_UMTS_STATUS_LEN)) { + netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n", + __func__, be16_to_cpu(lsi->length), + (u32)SIERRA_NET_LSI_UMTS_STATUS_LEN); + return -1; } /* Validate the protocol - only support UMTS for now */ - if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS) { - struct lsi_umts_single *single = (struct lsi_umts_single *)lsi; - - /* Validate the link type */ - if (single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV4 && - single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV6) { - netdev_err(dev->net, "Link type unsupported: 0x%02x\n", - single->link_type); - return -1; - } - expected_length = SIERRA_NET_LSI_UMTS_STATUS_LEN; - } else if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS_DS) { - expected_length = SIERRA_NET_LSI_UMTS_DS_STATUS_LEN; - } else { + if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) { netdev_err(dev->net, "Protocol unsupported, 0x%02x\n", - lsi->protocol); + lsi->protocol); return -1; } - if (be16_to_cpu(lsi->length) != expected_length) { - netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n", - __func__, be16_to_cpu(lsi->length), expected_length); + /* Validate the link type */ + if (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) { + netdev_err(dev->net, "Link type unsupported: 0x%02x\n", + lsi->link_type); return -1; } /* Validate the coverage */ - if (lsi->coverage == SIERRA_NET_COVERAGE_NONE || - lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) { + if (lsi->coverage == SIERRA_NET_COVERAGE_NONE + || lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) { netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage); return 0; } + /* Validate the session state */ + if (lsi->session_state == SIERRA_NET_SESSION_IDLE) { + netdev_err(dev->net, "Session idle, 0x%02x\n", + lsi->session_state); + return 0; + } + /* Set link_sense true */ return 1; } @@ -694,6 +662,7 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) u8 numendpoints; u16 fwattr = 0; int status; + struct ethhdr *eth; struct sierra_net_data *priv; static const u8 sync_tmplate[sizeof(priv->sync_msg)] = { 0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00}; @@ -731,6 +700,11 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter); dev->net->dev_addr[ETH_ALEN-1] = ifacenum; + /* we will have to manufacture ethernet headers, prepare template */ + eth = (struct ethhdr *)priv->ethr_hdr_tmpl; + memcpy(ð->h_dest, dev->net->dev_addr, ETH_ALEN); + eth->h_proto = cpu_to_be16(ETH_P_IP); + /* prepare shutdown message template */ memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg)); /* set context index initially to 0 - prepares tx hdr template */ @@ -859,14 +833,9 @@ static int sierra_net_rx_fixup(struct usbnet *dev, struct sk_buff *skb) skb_pull(skb, hh.hdrlen); - /* We are going to accept this packet, prepare it. - * In case protocol is IPv6, keep it, otherwise force IPv4. - */ - skb_reset_mac_header(skb); - if (eth_hdr(skb)->h_proto != cpu_to_be16(ETH_P_IPV6)) - eth_hdr(skb)->h_proto = cpu_to_be16(ETH_P_IP); - eth_zero_addr(eth_hdr(skb)->h_source); - memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN); + /* We are going to accept this packet, prepare it */ + memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl, + ETH_HLEN); /* Last packet in batch handled by usbnet */ if (hh.payload_len.word == skb->len) diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 478937418a33..30033dbe6662 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -81,9 +81,6 @@ static bool turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); -static int smsc75xx_link_ok_nopm(struct usbnet *dev); -static int smsc75xx_phy_gig_workaround(struct usbnet *dev); - static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { @@ -843,9 +840,6 @@ static int smsc75xx_phy_initialize(struct usbnet *dev) return -EIO; } - /* phy workaround for gig link */ - smsc75xx_phy_gig_workaround(dev); - smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); @@ -951,11 +945,10 @@ static int smsc75xx_set_features(struct net_device *netdev, /* it's racing here! */ ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); - if (ret < 0) { + if (ret < 0) netdev_warn(dev->net, "Error writing RFE_CTL\n"); - return ret; - } - return 0; + + return ret; } static int smsc75xx_wait_ready(struct usbnet *dev, int in_pm) @@ -984,62 +977,6 @@ static int smsc75xx_wait_ready(struct usbnet *dev, int in_pm) return -EIO; } -static int smsc75xx_phy_gig_workaround(struct usbnet *dev) -{ - struct mii_if_info *mii = &dev->mii; - int ret = 0, timeout = 0; - u32 buf, link_up = 0; - - /* Set the phy in Gig loopback */ - smsc75xx_mdio_write(dev->net, mii->phy_id, MII_BMCR, 0x4040); - - /* Wait for the link up */ - do { - link_up = smsc75xx_link_ok_nopm(dev); - usleep_range(10000, 20000); - timeout++; - } while ((!link_up) && (timeout < 1000)); - - if (timeout >= 1000) { - netdev_warn(dev->net, "Timeout waiting for PHY link up\n"); - return -EIO; - } - - /* phy reset */ - ret = smsc75xx_read_reg(dev, PMT_CTL, &buf); - if (ret < 0) { - netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret); - return ret; - } - - buf |= PMT_CTL_PHY_RST; - - ret = smsc75xx_write_reg(dev, PMT_CTL, buf); - if (ret < 0) { - netdev_warn(dev->net, "Failed to write PMT_CTL: %d\n", ret); - return ret; - } - - timeout = 0; - do { - usleep_range(10000, 20000); - ret = smsc75xx_read_reg(dev, PMT_CTL, &buf); - if (ret < 0) { - netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", - ret); - return ret; - } - timeout++; - } while ((buf & PMT_CTL_PHY_RST) && (timeout < 100)); - - if (timeout >= 100) { - netdev_warn(dev->net, "timeout waiting for PHY Reset\n"); - return -EIO; - } - - return 0; -} - static int smsc75xx_reset(struct usbnet *dev) { struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); @@ -2256,9 +2193,13 @@ static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev, { u32 tx_cmd_a, tx_cmd_b; - if (skb_cow_head(skb, SMSC75XX_TX_OVERHEAD)) { + if (skb_headroom(skb) < SMSC75XX_TX_OVERHEAD) { + struct sk_buff *skb2 = + skb_copy_expand(skb, SMSC75XX_TX_OVERHEAD, 0, flags); dev_kfree_skb_any(skb); - return NULL; + skb = skb2; + if (!skb) + return NULL; } tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN) | TX_CMD_A_FCS; diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c index aadfe1d1c37e..4a1e9c489f1f 100644 --- a/drivers/net/usb/sr9700.c +++ b/drivers/net/usb/sr9700.c @@ -456,9 +456,14 @@ static struct sk_buff *sr9700_tx_fixup(struct usbnet *dev, struct sk_buff *skb, len = skb->len; - if (skb_cow_head(skb, SR_TX_OVERHEAD)) { + if (skb_headroom(skb) < SR_TX_OVERHEAD) { + struct sk_buff *skb2; + + skb2 = skb_copy_expand(skb, SR_TX_OVERHEAD, 0, flags); dev_kfree_skb_any(skb); - return NULL; + skb = skb2; + if (!skb) + return NULL; } __skb_push(skb, SR_TX_OVERHEAD); diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 9710cf71054a..c2ea4e5666fb 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1990,10 +1990,6 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, elength = 1; goto next_desc; } - if ((buflen < elength) || (elength < 3)) { - dev_err(&intf->dev, "invalid descriptor buffer length\n"); - break; - } if (buffer[1] != USB_DT_CS_INTERFACE) { dev_err(&intf->dev, "skipping garbage\n"); goto next_desc; diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 6b4cc1c2e6b4..ba21d072be31 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -399,9 +399,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, if (ifmp && (dev->ifindex != 0)) peer->ifindex = ifmp->ifi_index; - peer->gso_max_size = dev->gso_max_size; - peer->gso_max_segs = dev->gso_max_segs; - err = register_netdevice(peer); put_net(net); net = NULL; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 2759d386ade7..f94ab786088f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -47,16 +47,8 @@ module_param(gso, bool, 0444); */ DECLARE_EWMA(pkt_len, 1, 64) -/* With mergeable buffers we align buffer address and use the low bits to - * encode its true size. Buffer size is up to 1 page so we need to align to - * square root of page size to ensure we reserve enough bits to encode the true - * size. - */ -#define MERGEABLE_BUFFER_MIN_ALIGN_SHIFT ((PAGE_SHIFT + 1) / 2) - /* Minimum alignment for mergeable packet buffers. */ -#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, \ - 1 << MERGEABLE_BUFFER_MIN_ALIGN_SHIFT) +#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, 256) #define VIRTNET_DRIVER_VERSION "1.0.0" @@ -556,12 +548,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, hdr = skb_vnet_hdr(skb); sg_init_table(rq->sg, 2); sg_set_buf(rq->sg, hdr, vi->hdr_len); - - err = skb_to_sgvec(skb, rq->sg + 1, 0, skb->len); - if (unlikely(err < 0)) { - dev_kfree_skb(skb); - return err; - } + skb_to_sgvec(skb, rq->sg + 1, 0, skb->len); err = virtqueue_add_inbuf(rq->vq, rq->sg, 2, skb, gfp); if (err < 0) @@ -863,7 +850,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) struct virtio_net_hdr_mrg_rxbuf *hdr; const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; struct virtnet_info *vi = sq->vq->vdev->priv; - int num_sg; + unsigned num_sg; unsigned hdr_len = vi->hdr_len; bool can_push; @@ -916,16 +903,11 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) if (can_push) { __skb_push(skb, hdr_len); num_sg = skb_to_sgvec(skb, sq->sg, 0, skb->len); - if (unlikely(num_sg < 0)) - return num_sg; /* Pull header back to avoid skew in tx bytes calculations. */ __skb_pull(skb, hdr_len); } else { sg_set_buf(sq->sg, hdr, hdr_len); - num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len); - if (unlikely(num_sg < 0)) - return num_sg; - num_sg++; + num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1; } return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb, GFP_ATOMIC); } @@ -1433,7 +1415,6 @@ static const struct net_device_ops virtnet_netdev = { #ifdef CONFIG_NET_RX_BUSY_POLL .ndo_busy_poll = virtnet_busy_poll, #endif - .ndo_features_check = passthru_features_check, }; static void virtnet_config_changed_work(struct work_struct *work) @@ -1484,11 +1465,6 @@ static void virtnet_free_queues(struct virtnet_info *vi) netif_napi_del(&vi->rq[i].napi); } - /* We called napi_hash_del() before netif_napi_del(), - * we need to respect an RCU grace period before freeing vi->rq - */ - synchronize_net(); - kfree(vi->rq); kfree(vi->sq); } @@ -1912,8 +1888,8 @@ static int virtnet_probe(struct virtio_device *vdev) /* Assume link up if device can't report link status, otherwise get link status from config. */ - netif_carrier_off(dev); if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) { + netif_carrier_off(dev); schedule_work(&vi->config_work); } else { vi->status = VIRTIO_NET_S_LINK_UP; diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 419c045d0752..0cbf520cea77 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1563,6 +1563,7 @@ static void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq, rq->rx_ring[i].basePA); rq->rx_ring[i].base = NULL; } + rq->buf_info[i] = NULL; } if (rq->comp_ring.base) { @@ -1577,7 +1578,6 @@ static void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq, (rq->rx_ring[0].size + rq->rx_ring[1].size); dma_free_coherent(&adapter->pdev->dev, sz, rq->buf_info[0], rq->buf_info_pa); - rq->buf_info[0] = rq->buf_info[1] = NULL; } } @@ -2789,11 +2789,6 @@ vmxnet3_force_close(struct vmxnet3_adapter *adapter) /* we need to enable NAPI, otherwise dev_close will deadlock */ for (i = 0; i < adapter->num_rx_queues; i++) napi_enable(&adapter->rx_queue[i].napi); - /* - * Need to clear the quiesce bit to ensure that vmxnet3_close - * can quiesce the device properly - */ - clear_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state); dev_close(adapter->netdev); } diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index d3d59122a357..903bda437839 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -301,9 +301,7 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, .flowi4_tos = RT_TOS(ip4h->tos), .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_L3MDEV_SRC | FLOWI_FLAG_SKIP_NH_OIF, - .flowi4_proto = ip4h->protocol, .daddr = ip4h->daddr, - .saddr = ip4h->saddr, }; if (vrf_send_v4_prep(skb, &fl4, vrf_dev)) @@ -345,7 +343,6 @@ static netdev_tx_t is_ip_tx_frame(struct sk_buff *skb, struct net_device *dev) static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev) { - int len = skb->len; netdev_tx_t ret = is_ip_tx_frame(skb, dev); if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { @@ -353,7 +350,7 @@ static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev) u64_stats_update_begin(&dstats->syncp); dstats->tx_pkts++; - dstats->tx_bytes += len; + dstats->tx_bytes += skb->len; u64_stats_update_end(&dstats->syncp); } else { this_cpu_inc(dev->dstats->tx_drps); @@ -413,8 +410,6 @@ static int vrf_finish_output6(struct net *net, struct sock *sk, struct in6_addr *nexthop; int ret; - nf_reset(skb); - skb->protocol = htons(ETH_P_IPV6); skb->dev = dev; @@ -526,8 +521,6 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s u32 nexthop; int ret = -EINVAL; - nf_reset(skb); - /* Be paranoid, rather than too clever. */ if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) { struct sk_buff *skb2; @@ -550,15 +543,13 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s neigh = __ipv4_neigh_lookup_noref(dev, nexthop); if (unlikely(!neigh)) neigh = __neigh_create(&arp_tbl, &nexthop, dev, false); - if (!IS_ERR(neigh)) { + if (!IS_ERR(neigh)) ret = dst_neigh_output(dst, neigh, skb); - rcu_read_unlock_bh(); - return ret; - } rcu_read_unlock_bh(); err: - vrf_tx_error(skb->dev, skb); + if (unlikely(ret < 0)) + vrf_tx_error(skb->dev, skb); return ret; } @@ -735,15 +726,15 @@ static int vrf_del_slave(struct net_device *dev, struct net_device *port_dev) static void vrf_dev_uninit(struct net_device *dev) { struct net_vrf *vrf = netdev_priv(dev); -// struct slave_queue *queue = &vrf->queue; -// struct list_head *head = &queue->all_slaves; -// struct slave *slave, *next; + struct slave_queue *queue = &vrf->queue; + struct list_head *head = &queue->all_slaves; + struct slave *slave, *next; vrf_rtable_destroy(vrf); vrf_rt6_destroy(vrf); -// list_for_each_entry_safe(slave, next, head, list) -// vrf_del_slave(dev, slave->dev); + list_for_each_entry_safe(slave, next, head, list) + vrf_del_slave(dev, slave->dev); free_percpu(dev->dstats); dev->dstats = NULL; @@ -916,14 +907,6 @@ static int vrf_validate(struct nlattr *tb[], struct nlattr *data[]) static void vrf_dellink(struct net_device *dev, struct list_head *head) { - struct net_vrf *vrf = netdev_priv(dev); - struct slave_queue *queue = &vrf->queue; - struct list_head *all_slaves = &queue->all_slaves; - struct slave *slave, *next; - - list_for_each_entry_safe(slave, next, all_slaves, list) - vrf_del_slave(dev, slave->dev); - unregister_netdevice_queue(dev, head); } @@ -936,8 +919,6 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev, return -EINVAL; vrf->tb_id = nla_get_u32(data[IFLA_VRF_TABLE]); - if (vrf->tb_id == RT_TABLE_UNSPEC) - return -EINVAL; dev->priv_flags |= IFF_L3MDEV_MASTER; diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index c41378214ede..3c0df70e2f53 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -77,8 +77,6 @@ static const u8 all_zeros_mac[ETH_ALEN]; static int vxlan_sock_add(struct vxlan_dev *vxlan); -static void vxlan_vs_del_dev(struct vxlan_dev *vxlan); - /* per-network namespace private data for this module */ struct vxlan_net { struct list_head vxlan_list; @@ -595,7 +593,7 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, } } - pp = call_gro_receive(eth_gro_receive, head, skb); + pp = eth_gro_receive(head, skb); out: skb_gro_remcsum_cleanup(skb, &grc); @@ -962,7 +960,7 @@ static bool vxlan_snoop(struct net_device *dev, return false; /* Don't migrate static entries, drop packets */ - if (f->state & (NUD_PERMANENT | NUD_NOARP)) + if (f->state & NUD_NOARP) return true; if (net_ratelimit()) @@ -1054,8 +1052,6 @@ static void __vxlan_sock_release(struct vxlan_sock *vs) static void vxlan_sock_release(struct vxlan_dev *vxlan) { - vxlan_vs_del_dev(vxlan); - __vxlan_sock_release(vxlan->vn4_sock); #if IS_ENABLED(CONFIG_IPV6) __vxlan_sock_release(vxlan->vn6_sock); @@ -1258,7 +1254,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) /* Need Vxlan and inner Ethernet header to be present */ if (!pskb_may_pull(skb, VXLAN_HLEN)) - goto drop; + goto error; vxh = (struct vxlanhdr *)(udp_hdr(skb) + 1); flags = ntohl(vxh->vx_flags); @@ -1348,7 +1344,13 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) bad_flags: netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n", ntohl(vxh->vx_flags), ntohl(vxh->vx_vni)); - goto drop; + +error: + if (tun_dst) + dst_release((struct dst_entry *)tun_dst); + + /* Return non vxlan pkt */ + return 1; } static int arp_reduce(struct net_device *dev, struct sk_buff *skb) @@ -2240,7 +2242,7 @@ static void vxlan_cleanup(unsigned long arg) = container_of(p, struct vxlan_fdb, hlist); unsigned long timeout; - if (f->state & (NUD_PERMANENT | NUD_NOARP)) + if (f->state & NUD_PERMANENT) continue; timeout = f->used + vxlan->cfg.age_interval * HZ; @@ -2259,15 +2261,6 @@ static void vxlan_cleanup(unsigned long arg) mod_timer(&vxlan->age_timer, next_timer); } -static void vxlan_vs_del_dev(struct vxlan_dev *vxlan) -{ - struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); - - spin_lock(&vn->sock_lock); - hlist_del_init_rcu(&vxlan->hlist); - spin_unlock(&vn->sock_lock); -} - static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan) { struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); @@ -2377,43 +2370,29 @@ static void vxlan_set_multicast_list(struct net_device *dev) { } -static int __vxlan_change_mtu(struct net_device *dev, - struct net_device *lowerdev, - struct vxlan_rdst *dst, int new_mtu, bool strict) +static int vxlan_change_mtu(struct net_device *dev, int new_mtu) { - int max_mtu = IP_MAX_MTU; + struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_rdst *dst = &vxlan->default_dst; + struct net_device *lowerdev; + int max_mtu; - if (lowerdev) - max_mtu = lowerdev->mtu; + lowerdev = __dev_get_by_index(vxlan->net, dst->remote_ifindex); + if (lowerdev == NULL) + return eth_change_mtu(dev, new_mtu); if (dst->remote_ip.sa.sa_family == AF_INET6) - max_mtu -= VXLAN6_HEADROOM; + max_mtu = lowerdev->mtu - VXLAN6_HEADROOM; else - max_mtu -= VXLAN_HEADROOM; + max_mtu = lowerdev->mtu - VXLAN_HEADROOM; - if (new_mtu < 68) + if (new_mtu < 68 || new_mtu > max_mtu) return -EINVAL; - if (new_mtu > max_mtu) { - if (strict) - return -EINVAL; - - new_mtu = max_mtu; - } - dev->mtu = new_mtu; return 0; } -static int vxlan_change_mtu(struct net_device *dev, int new_mtu) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_rdst *dst = &vxlan->default_dst; - struct net_device *lowerdev = __dev_get_by_index(vxlan->net, - dst->remote_ifindex); - return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true); -} - static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb, struct ip_tunnel_info *info, __be16 sport, __be16 dport) @@ -2613,7 +2592,7 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) if (data[IFLA_VXLAN_ID]) { __u32 id = nla_get_u32(data[IFLA_VXLAN_ID]); - if (id >= VXLAN_N_VID) + if (id >= VXLAN_VID_MASK) return -ERANGE; } @@ -2789,7 +2768,6 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, int err; bool use_ipv6 = false; __be16 default_port = vxlan->cfg.dst_port; - struct net_device *lowerdev = NULL; vxlan->net = src_net; @@ -2810,7 +2788,9 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, } if (conf->remote_ifindex) { - lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex); + struct net_device *lowerdev + = __dev_get_by_index(src_net, conf->remote_ifindex); + dst->remote_ifindex = conf->remote_ifindex; if (!lowerdev) { @@ -2834,17 +2814,6 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, needed_headroom = lowerdev->hard_header_len; } - if (lowerdev) { - dev->gso_max_size = lowerdev->gso_max_size; - dev->gso_max_segs = lowerdev->gso_max_segs; - } - - if (conf->mtu) { - err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false); - if (err) - return err; - } - if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA) needed_headroom += VXLAN6_HEADROOM; else @@ -3022,9 +2991,6 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev, if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL]) conf.flags |= VXLAN_F_REMCSUM_NOPARTIAL; - if (tb[IFLA_MTU]) - conf.mtu = nla_get_u32(tb[IFLA_MTU]); - err = vxlan_dev_configure(src_net, dev, &conf); switch (err) { case -ENODEV: @@ -3046,6 +3012,12 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev, static void vxlan_dellink(struct net_device *dev, struct list_head *head) { struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); + + spin_lock(&vn->sock_lock); + if (!hlist_unhashed(&vxlan->hlist)) + hlist_del_rcu(&vxlan->hlist); + spin_unlock(&vn->sock_lock); gro_cells_destroy(&vxlan->gro_cells); list_del(&vxlan->next); diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index 4842344a96f1..0d7645581f91 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c @@ -574,10 +574,7 @@ static void ppp_timer(unsigned long arg) ppp_cp_event(proto->dev, proto->pid, TO_GOOD, 0, 0, 0, NULL); proto->restart_counter--; - } else if (netif_carrier_ok(proto->dev)) - ppp_cp_event(proto->dev, proto->pid, TO_GOOD, 0, 0, - 0, NULL); - else + } else ppp_cp_event(proto->dev, proto->pid, TO_BAD, 0, 0, 0, NULL); break; diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index c178e1218347..317bc79cc8b9 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -1385,7 +1385,7 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ case 0x001: printk(KERN_WARNING "%s: Master Abort (naughty)\n", dev->name); break; - case 0x002: + case 0x010: printk(KERN_WARNING "%s: Target Abort (not so naughty)\n", dev->name); break; default: diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c index 2b064998915f..db363856e0b5 100644 --- a/drivers/net/wan/pc300too.c +++ b/drivers/net/wan/pc300too.c @@ -347,7 +347,6 @@ static int pc300_pci_init_one(struct pci_dev *pdev, card->rambase == NULL) { pr_err("ioremap() failed\n"); pc300_pci_remove_one(pdev); - return -ENOMEM; } /* PLX PCI 9050 workaround for local configuration register read bug */ diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index f8eb66ef2944..e7f5910a6519 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -467,9 +467,6 @@ int i2400mu_probe(struct usb_interface *iface, struct i2400mu *i2400mu; struct usb_device *usb_dev = interface_to_usbdev(iface); - if (iface->cur_altsetting->desc.bNumEndpoints < 4) - return -ENODEV; - if (usb_dev->speed != USB_SPEED_HIGH) dev_err(dev, "device not connected as high speed\n"); diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 0c23768aa1ec..531de256d58d 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -67,7 +67,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA988X_BOARD_DATA_SZ, .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ, }, - .decap_align_bytes = 4, }, { .id = QCA6174_HW_2_1_VERSION, @@ -86,7 +85,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, - .decap_align_bytes = 4, }, { .id = QCA6174_HW_2_1_VERSION, @@ -105,7 +103,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, - .decap_align_bytes = 4, }, { .id = QCA6174_HW_3_0_VERSION, @@ -124,7 +121,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, - .decap_align_bytes = 4, }, { .id = QCA6174_HW_3_2_VERSION, @@ -144,7 +140,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, - .decap_align_bytes = 4, }, { .id = QCA99X0_HW_2_0_DEV_VERSION, @@ -164,7 +159,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA99X0_BOARD_DATA_SZ, .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, }, - .decap_align_bytes = 1, }, { .id = QCA9377_HW_1_0_DEV_VERSION, @@ -183,7 +177,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA9377_BOARD_DATA_SZ, .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, }, - .decap_align_bytes = 4, }, { .id = QCA9377_HW_1_1_DEV_VERSION, @@ -202,7 +195,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA9377_BOARD_DATA_SZ, .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, }, - .decap_align_bytes = 4, }, }; @@ -556,11 +548,8 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) "boot get otp board id result 0x%08x board_id %d chip_id %d\n", result, board_id, chip_id); - if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0 || - (board_id == 0)) { - ath10k_warn(ar, "board id is not exist in otp, ignore it\n"); + if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0) return -EOPNOTSUPP; - } ar->id.bmi_ids_valid = true; ar->id.bmi_board_id = board_id; @@ -1618,12 +1607,6 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) goto err_wmi_detach; } - /* If firmware indicates Full Rx Reorder support it must be used in a - * slightly different manner. Let HTT code know. - */ - ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER, - ar->wmi.svc_map)); - status = ath10k_htt_rx_alloc(&ar->htt); if (status) { ath10k_err(ar, "failed to alloc htt rx: %d\n", status); @@ -1686,6 +1669,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) goto err_hif_stop; } + /* If firmware indicates Full Rx Reorder support it must be used in a + * slightly different manner. Let HTT code know. + */ + ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER, + ar->wmi.svc_map)); + status = ath10k_htt_rx_ring_refill(ar); if (status) { ath10k_err(ar, "failed to refill htt rx ring: %d\n", status); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 257836a0cfbc..858d75f49a9f 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -670,10 +670,6 @@ struct ath10k { size_t board_size; size_t board_ext_size; } fw; - - /* Number of bytes used for alignment in rx_hdr_status */ - int decap_align_bytes; - } hw_params; const struct firmware *board; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 30c357567054..1a88a24ffeac 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -1892,15 +1892,6 @@ static ssize_t ath10k_write_simulate_radar(struct file *file, size_t count, loff_t *ppos) { struct ath10k *ar = file->private_data; - struct ath10k_vif *arvif; - - /* Just check for for the first vif alone, as all the vifs will be - * sharing the same channel and if the channel is disabled, all the - * vifs will share the same 'is_started' state. - */ - arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list); - if (!arvif->is_started) - return -EINVAL; ieee80211_radar_detected(ar->hw); diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index b32c47fe926d..6060dda4e910 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -979,7 +979,7 @@ static void ath10k_process_rx(struct ath10k *ar, *status = *rx_status; ath10k_dbg(ar, ATH10K_DBG_DATA, - "rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n", + "rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", skb, skb->len, ieee80211_get_SA(hdr), @@ -1076,21 +1076,7 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar, hdr = (void *)msdu->data; /* Tail */ - if (status->flag & RX_FLAG_IV_STRIPPED) { - skb_trim(msdu, msdu->len - - ath10k_htt_rx_crypto_tail_len(ar, enctype)); - } else { - /* MIC */ - if ((status->flag & RX_FLAG_MIC_STRIPPED) && - enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) - skb_trim(msdu, msdu->len - 8); - - /* ICV */ - if (status->flag & RX_FLAG_ICV_STRIPPED && - enctype != HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) - skb_trim(msdu, msdu->len - - ath10k_htt_rx_crypto_tail_len(ar, enctype)); - } + skb_trim(msdu, msdu->len - ath10k_htt_rx_crypto_tail_len(ar, enctype)); /* MMIC */ if (!ieee80211_has_morefrags(hdr->frame_control) && @@ -1109,14 +1095,12 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar, static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar, struct sk_buff *msdu, struct ieee80211_rx_status *status, - const u8 first_hdr[64], - enum htt_rx_mpdu_encrypt_type enctype) + const u8 first_hdr[64]) { struct ieee80211_hdr *hdr; size_t hdr_len; u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; - int bytes_aligned = ar->hw_params.decap_align_bytes; /* Delivered decapped frame: * [nwifi 802.11 header] <-- replaced with 802.11 hdr @@ -1139,14 +1123,6 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar, /* push original 802.11 header */ hdr = (struct ieee80211_hdr *)first_hdr; hdr_len = ieee80211_hdrlen(hdr->frame_control); - - if (!(status->flag & RX_FLAG_IV_STRIPPED)) { - memcpy(skb_push(msdu, - ath10k_htt_rx_crypto_param_len(ar, enctype)), - (void *)hdr + round_up(hdr_len, bytes_aligned), - ath10k_htt_rx_crypto_param_len(ar, enctype)); - } - memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); /* original 802.11 header has a different DA and in @@ -1166,7 +1142,6 @@ static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar, size_t hdr_len, crypto_len; void *rfc1042; bool is_first, is_last, is_amsdu; - int bytes_aligned = ar->hw_params.decap_align_bytes; rxd = (void *)msdu->data - sizeof(*rxd); hdr = (void *)rxd->rx_hdr_status; @@ -1183,8 +1158,8 @@ static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar, hdr_len = ieee80211_hdrlen(hdr->frame_control); crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype); - rfc1042 += round_up(hdr_len, bytes_aligned) + - round_up(crypto_len, bytes_aligned); + rfc1042 += round_up(hdr_len, 4) + + round_up(crypto_len, 4); } if (is_amsdu) @@ -1205,7 +1180,6 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, void *rfc1042; u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; - int bytes_aligned = ar->hw_params.decap_align_bytes; /* Delivered decapped frame: * [eth header] <-- replaced with 802.11 hdr & rfc1042/llc @@ -1229,14 +1203,6 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, /* push original 802.11 header */ hdr = (struct ieee80211_hdr *)first_hdr; hdr_len = ieee80211_hdrlen(hdr->frame_control); - - if (!(status->flag & RX_FLAG_IV_STRIPPED)) { - memcpy(skb_push(msdu, - ath10k_htt_rx_crypto_param_len(ar, enctype)), - (void *)hdr + round_up(hdr_len, bytes_aligned), - ath10k_htt_rx_crypto_param_len(ar, enctype)); - } - memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); /* original 802.11 header has a different DA and in @@ -1250,12 +1216,10 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar, struct sk_buff *msdu, struct ieee80211_rx_status *status, - const u8 first_hdr[64], - enum htt_rx_mpdu_encrypt_type enctype) + const u8 first_hdr[64]) { struct ieee80211_hdr *hdr; size_t hdr_len; - int bytes_aligned = ar->hw_params.decap_align_bytes; /* Delivered decapped frame: * [amsdu header] <-- replaced with 802.11 hdr @@ -1267,14 +1231,6 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar, hdr = (struct ieee80211_hdr *)first_hdr; hdr_len = ieee80211_hdrlen(hdr->frame_control); - - if (!(status->flag & RX_FLAG_IV_STRIPPED)) { - memcpy(skb_push(msdu, - ath10k_htt_rx_crypto_param_len(ar, enctype)), - (void *)hdr + round_up(hdr_len, bytes_aligned), - ath10k_htt_rx_crypto_param_len(ar, enctype)); - } - memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); } @@ -1309,15 +1265,13 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar, is_decrypted); break; case RX_MSDU_DECAP_NATIVE_WIFI: - ath10k_htt_rx_h_undecap_nwifi(ar, msdu, status, first_hdr, - enctype); + ath10k_htt_rx_h_undecap_nwifi(ar, msdu, status, first_hdr); break; case RX_MSDU_DECAP_ETHERNET2_DIX: ath10k_htt_rx_h_undecap_eth(ar, msdu, status, first_hdr, enctype); break; case RX_MSDU_DECAP_8023_SNAP_LLC: - ath10k_htt_rx_h_undecap_snap(ar, msdu, status, first_hdr, - enctype); + ath10k_htt_rx_h_undecap_snap(ar, msdu, status, first_hdr); break; } } @@ -1360,8 +1314,7 @@ static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu) static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, struct sk_buff_head *amsdu, - struct ieee80211_rx_status *status, - bool fill_crypt_header) + struct ieee80211_rx_status *status) { struct sk_buff *first; struct sk_buff *last; @@ -1371,6 +1324,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, enum htt_rx_mpdu_encrypt_type enctype; u8 first_hdr[64]; u8 *qos; + size_t hdr_len; bool has_fcs_err; bool has_crypto_err; bool has_tkip_err; @@ -1391,17 +1345,15 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, * decapped header. It'll be used for undecapping of each MSDU. */ hdr = (void *)rxd->rx_hdr_status; - memcpy(first_hdr, hdr, RX_HTT_HDR_STATUS_LEN); + hdr_len = ieee80211_hdrlen(hdr->frame_control); + memcpy(first_hdr, hdr, hdr_len); /* Each A-MSDU subframe will use the original header as the base and be * reported as a separate MSDU so strip the A-MSDU bit from QoS Ctl. */ hdr = (void *)first_hdr; - - if (ieee80211_is_data_qos(hdr->frame_control)) { - qos = ieee80211_get_qos_ctl(hdr); - qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; - } + qos = ieee80211_get_qos_ctl(hdr); + qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; /* Some attention flags are valid only in the last MSDU. */ last = skb_peek_tail(amsdu); @@ -1435,17 +1387,11 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, if (has_tkip_err) status->flag |= RX_FLAG_MMIC_ERROR; - if (is_decrypted) { + if (is_decrypted) status->flag |= RX_FLAG_DECRYPTED | + RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; - if (fill_crypt_header) - status->flag |= RX_FLAG_MIC_STRIPPED | - RX_FLAG_ICV_STRIPPED; - else - status->flag |= RX_FLAG_IV_STRIPPED; - } - skb_queue_walk(amsdu, msdu) { ath10k_htt_rx_h_csum_offload(msdu); ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype, @@ -1458,9 +1404,6 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, if (!is_decrypted) continue; - if (fill_crypt_header) - continue; - hdr = (void *)msdu->data; hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED); } @@ -1471,9 +1414,6 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar, struct ieee80211_rx_status *status) { struct sk_buff *msdu; - struct sk_buff *first_subframe; - - first_subframe = skb_peek(amsdu); while ((msdu = __skb_dequeue(amsdu))) { /* Setup per-MSDU flags */ @@ -1482,13 +1422,6 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar, else status->flag |= RX_FLAG_AMSDU_MORE; - if (msdu == first_subframe) { - first_subframe = NULL; - status->flag &= ~RX_FLAG_ALLOW_SAME_PN; - } else { - status->flag |= RX_FLAG_ALLOW_SAME_PN; - } - ath10k_process_rx(ar, status, msdu); } } @@ -1674,7 +1607,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0); ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); - ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true); + ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status); ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); } @@ -1720,7 +1653,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); - ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true); + ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status); ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); if (fw_desc_len > 0) { @@ -2019,7 +1952,7 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) */ ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id); ath10k_htt_rx_h_filter(ar, &amsdu, status); - ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false); + ath10k_htt_rx_h_mpdu(ar, &amsdu, status); ath10k_htt_rx_h_deliver(ar, &amsdu, status); break; case -EAGAIN: diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 916b9b12edd2..1e1bef349487 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1127,36 +1127,6 @@ static int ath10k_monitor_recalc(struct ath10k *ar) return ath10k_monitor_stop(ar); } -static bool ath10k_mac_can_set_cts_prot(struct ath10k_vif *arvif) -{ - struct ath10k *ar = arvif->ar; - - lockdep_assert_held(&ar->conf_mutex); - - if (!arvif->is_started) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "defer cts setup, vdev is not ready yet\n"); - return false; - } - - return true; -} - -static int ath10k_mac_set_cts_prot(struct ath10k_vif *arvif) -{ - struct ath10k *ar = arvif->ar; - u32 vdev_param; - - lockdep_assert_held(&ar->conf_mutex); - - vdev_param = ar->wmi.vdev_param->protection_mode; - - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d cts_protection %d\n", - arvif->vdev_id, arvif->use_cts_prot); - - return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, - arvif->use_cts_prot ? 1 : 0); -} - static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif) { struct ath10k *ar = arvif->ar; @@ -4210,8 +4180,7 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar) lockdep_assert_held(&ar->conf_mutex); list_for_each_entry(arvif, &ar->arvifs, list) { - if (arvif->txpower <= 0) - continue; + WARN_ON(arvif->txpower < 0); if (txpower == -1) txpower = arvif->txpower; @@ -4219,8 +4188,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar) txpower = min(txpower, arvif->txpower); } - if (txpower == -1) - return 0; + if (WARN_ON(txpower == -1)) + return -EINVAL; ret = ath10k_mac_txpower_setup(ar, txpower); if (ret) { @@ -4818,18 +4787,20 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ERP_CTS_PROT) { arvif->use_cts_prot = info->use_cts_prot; + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d cts_prot %d\n", + arvif->vdev_id, info->use_cts_prot); ret = ath10k_recalc_rtscts_prot(arvif); if (ret) ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n", arvif->vdev_id, ret); - if (ath10k_mac_can_set_cts_prot(arvif)) { - ret = ath10k_mac_set_cts_prot(arvif); - if (ret) - ath10k_warn(ar, "failed to set cts protection for vdev %d: %d\n", - arvif->vdev_id, ret); - } + vdev_param = ar->wmi.vdev_param->protection_mode; + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, + info->use_cts_prot ? 1 : 0); + if (ret) + ath10k_warn(ar, "failed to set protection mode %d on vdev %i: %d\n", + info->use_cts_prot, arvif->vdev_id, ret); } if (changed & BSS_CHANGED_ERP_SLOT) { @@ -5285,8 +5256,9 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) sta->addr, smps, err); } - if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n", + if (changed & IEEE80211_RC_SUPP_RATES_CHANGED || + changed & IEEE80211_RC_NSS_CHANGED) { + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates/nss\n", sta->addr); err = ath10k_station_assoc(ar, arvif->vif, sta, true); @@ -5496,16 +5468,6 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, "mac vdev %d peer delete %pM (sta gone)\n", arvif->vdev_id, sta->addr); - if (sta->tdls) { - ret = ath10k_mac_tdls_peer_update(ar, arvif->vdev_id, - sta, - WMI_TDLS_PEER_STATE_TEARDOWN); - if (ret) - ath10k_warn(ar, "failed to update tdls peer state for %pM state %d: %i\n", - sta->addr, - WMI_TDLS_PEER_STATE_TEARDOWN, ret); - } - ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); if (ret) ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n", @@ -6311,20 +6273,10 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, { struct ath10k *ar = hw->priv; struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; - struct ath10k_vif *arvif = (void *)vif->drv_priv; - struct ath10k_peer *peer; u32 bw, smps; spin_lock_bh(&ar->data_lock); - peer = ath10k_peer_find(ar, arvif->vdev_id, sta->addr); - if (!peer) { - spin_unlock_bh(&ar->data_lock); - ath10k_warn(ar, "mac sta rc update failed to find peer %pM on vdev %i\n", - sta->addr, arvif->vdev_id); - return; - } - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", sta->addr, changed, sta->bandwidth, sta->rx_nss, @@ -6399,13 +6351,12 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static int ath10k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu) { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n", arvif->vdev_id, sta->addr, tid, action); @@ -6446,7 +6397,7 @@ ath10k_mac_update_rx_channel(struct ath10k *ar, lockdep_assert_held(&ar->data_lock); WARN_ON(ctx && vifs); - WARN_ON(vifs && !n_vifs); + WARN_ON(vifs && n_vifs != 1); /* FIXME: Sort of an optimization and a workaround. Peers and vifs are * on a linked list now. Doing a lookup peer -> vif -> chanctx for each @@ -6760,13 +6711,6 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, arvif->is_up = true; } - if (ath10k_mac_can_set_cts_prot(arvif)) { - ret = ath10k_mac_set_cts_prot(arvif); - if (ret) - ath10k_warn(ar, "failed to set cts protection for vdev %d: %d\n", - arvif->vdev_id, ret); - } - mutex_unlock(&ar->conf_mutex); return 0; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 907fd60c4241..930785a724e1 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3050,7 +3050,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, goto err_core_destroy; } - if (QCA_REV_6174(ar) || QCA_REV_9377(ar)) + if (QCA_REV_6174(ar)) ath10k_pci_override_ce_config(ar); ret = ath10k_pci_alloc_pipes(ar); diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c index a0e7eebc206a..4671cfbcd8f7 100644 --- a/drivers/net/wireless/ath/ath10k/spectral.c +++ b/drivers/net/wireless/ath/ath10k/spectral.c @@ -338,7 +338,7 @@ static ssize_t write_file_spec_scan_ctl(struct file *file, } else { res = -EINVAL; } - } else if (strncmp("background", buf, 10) == 0) { + } else if (strncmp("background", buf, 9) == 0) { res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND); } else if (strncmp("manual", buf, 6) == 0) { res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL); diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index cfed5808bc4e..8f4f6a892581 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -639,9 +639,6 @@ ath10k_wmi_vdev_spectral_conf(struct ath10k *ar, struct sk_buff *skb; u32 cmd_id; - if (!ar->wmi.ops->gen_vdev_spectral_conf) - return -EOPNOTSUPP; - skb = ar->wmi.ops->gen_vdev_spectral_conf(ar, arg); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -657,9 +654,6 @@ ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger, struct sk_buff *skb; u32 cmd_id; - if (!ar->wmi.ops->gen_vdev_spectral_enable) - return -EOPNOTSUPP; - skb = ar->wmi.ops->gen_vdev_spectral_enable(ar, vdev_id, trigger, enable); if (IS_ERR(skb)) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 02eea3c3b5d3..6fbd17b69469 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1105,10 +1105,8 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, struct ath10k_fw_stats_pdev *dst; src = data; - if (data_len < sizeof(*src)) { - kfree(tb); + if (data_len < sizeof(*src)) return -EPROTO; - } data += sizeof(*src); data_len -= sizeof(*src); @@ -1128,10 +1126,8 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, struct ath10k_fw_stats_vdev *dst; src = data; - if (data_len < sizeof(*src)) { - kfree(tb); + if (data_len < sizeof(*src)) return -EPROTO; - } data += sizeof(*src); data_len -= sizeof(*src); @@ -1149,10 +1145,8 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, struct ath10k_fw_stats_peer *dst; src = data; - if (data_len < sizeof(*src)) { - kfree(tb); + if (data_len < sizeof(*src)) return -EPROTO; - } data += sizeof(*src); data_len -= sizeof(*src); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index a8b2553e8988..72a4ef709577 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4826,8 +4826,7 @@ enum wmi_10_4_vdev_param { #define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3) #define WMI_TXBF_STS_CAP_OFFSET_LSB 4 -#define WMI_TXBF_STS_CAP_OFFSET_MASK 0x70 -#define WMI_TXBF_CONF_IMPLICIT_BF BIT(7) +#define WMI_TXBF_STS_CAP_OFFSET_MASK 0xf0 #define WMI_BF_SOUND_DIM_OFFSET_LSB 8 #define WMI_BF_SOUND_DIM_OFFSET_MASK 0xf00 diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 7c5f189cace7..654a1e33f827 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -939,10 +939,7 @@ static int open_file_eeprom(struct inode *inode, struct file *file) } for (i = 0; i < eesize; ++i) { - if (!ath5k_hw_nvram_read(ah, i, &val)) { - ret = -EIO; - goto freebuf; - } + AR5K_EEPROM_READ(i, val); buf[i] = val; } diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 16e052d02c94..dc44cfef7517 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -502,7 +502,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; return -EOPNOTSUPP; default: - return -EOPNOTSUPP; + WARN_ON(1); + return -EINVAL; } mutex_lock(&ah->lock); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index ef493271c712..8b4561e8ce1a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4176,7 +4176,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9531(ah)) ar9003_hw_internal_regulator_apply(ah); ar9003_hw_apply_tuning_caps(ah); - ar9003_hw_apply_minccapwr_thresh(ah, is2ghz); + ar9003_hw_apply_minccapwr_thresh(ah, chan); ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz); ar9003_hw_thermometer_apply(ah); ar9003_hw_thermo_cal_apply(ah); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 74670e08e6da..694ca2e680e5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -73,13 +73,13 @@ #define AR9300_OTP_BASE \ ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000) #define AR9300_OTP_STATUS \ - ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x31018 : 0x15f18) + ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30018 : 0x15f18) #define AR9300_OTP_STATUS_TYPE 0x7 #define AR9300_OTP_STATUS_VALID 0x4 #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 #define AR9300_OTP_STATUS_SM_BUSY 0x1 #define AR9300_OTP_READ_DATA \ - ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3101c : 0x15f1c) + ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3001c : 0x15f1c) enum targetPowerHTRates { HT_TARGET_RATE_0_8_16, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index fbc8c9a9014b..201425e7f9cb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1815,6 +1815,8 @@ static void ar9003_hw_spectral_scan_wait(struct ath_hw *ah) static void ar9003_hw_tx99_start(struct ath_hw *ah, u32 qnum) { REG_SET_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR); + REG_SET_BIT(ah, 0x9864, 0x7f000); + REG_SET_BIT(ah, 0x9924, 0x7f00fe); REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); REG_WRITE(ah, AR_CR, AR_CR_RXD); REG_WRITE(ah, AR_DLCL_IFS(qnum), 0); diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index a660e40f2df1..b42f4a963ef4 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -959,7 +959,6 @@ struct ath_softc { struct survey_info *cur_survey; struct survey_info survey[ATH9K_NUM_CHANNELS]; - spinlock_t intr_lock; struct tasklet_struct intr_tq; struct tasklet_struct bcon_tasklet; struct ath_hw *sc_ah; diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index 03945731eb65..a8762711ad74 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c @@ -528,9 +528,6 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) return 0; - if (!spec_priv->rfs_chan_spec_scan) - return 1; - /* Output buffers are full, no need to process anything * since there is no space to put the result anyway */ @@ -1075,7 +1072,7 @@ static struct rchan_callbacks rfs_spec_scan_cb = { void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) { - if (config_enabled(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { + if (config_enabled(CONFIG_ATH9K_DEBUGFS)) { relay_close(spec_priv->rfs_chan_spec_scan); spec_priv->rfs_chan_spec_scan = NULL; } @@ -1089,9 +1086,6 @@ void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, debugfs_phy, 1024, 256, &rfs_spec_scan_cb, NULL); - if (!spec_priv->rfs_chan_spec_scan) - return; - debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, debugfs_phy, spec_priv, diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index c92564b3ec85..165dd202c365 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -37,7 +37,6 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */ { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ { USB_DEVICE(0x0471, 0x209e) }, /* Philips (or NXP) PTA01 */ - { USB_DEVICE(0x1eda, 0x2315) }, /* AirTies */ { USB_DEVICE(0x0cf3, 0x7015), .driver_info = AR9287_USB }, /* Atheros */ @@ -1217,9 +1216,6 @@ static int send_eject_command(struct usb_interface *interface) u8 bulk_out_ep; int r; - if (iface_desc->desc.bNumEndpoints < 2) - return -ENODEV; - /* Find bulk out endpoint */ for (r = 1; r >= 0; r--) { endpoint = &iface_desc->endpoint[r].desc; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index e4281438c04f..a680a970b7f7 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1657,14 +1657,13 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw, static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { struct ath9k_htc_priv *priv = hw->priv; struct ath9k_htc_sta *ista; int ret = 0; - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 4435c7bbb625..41382f89abe1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1595,10 +1595,6 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) int count = 50; u32 reg, last_val; - /* Check if chip failed to wake up */ - if (REG_READ(ah, AR_CFG) == 0xdeadbeef) - return false; - if (AR_SREV_9300(ah)) return !ath9k_hw_detect_mac_hang(ah); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 0f5672f5c9ba..1bdeacf7b257 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -619,7 +619,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, common->bt_ant_diversity = 1; spin_lock_init(&common->cc_lock); - spin_lock_init(&sc->intr_lock); spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); spin_lock_init(&sc->chan_lock); @@ -870,8 +869,8 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE); - hw->wiphy->iface_combinations = if_comb; - hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); + hw->wiphy->iface_combinations = if_comb; + hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); } hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index d937c39b3a0b..bba85d1a6cd1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -805,12 +805,21 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_disable_interrupts); -static void __ath9k_hw_enable_interrupts(struct ath_hw *ah) +void ath9k_hw_enable_interrupts(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); u32 sync_default = AR_INTR_SYNC_DEFAULT; u32 async_mask; + if (!(ah->imask & ATH9K_INT_GLOBAL)) + return; + + if (!atomic_inc_and_test(&ah->intr_ref_cnt)) { + ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", + atomic_read(&ah->intr_ref_cnt)); + return; + } + if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah)) sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; @@ -832,39 +841,6 @@ static void __ath9k_hw_enable_interrupts(struct ath_hw *ah) ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); } - -void ath9k_hw_resume_interrupts(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - - if (!(ah->imask & ATH9K_INT_GLOBAL)) - return; - - if (atomic_read(&ah->intr_ref_cnt) != 0) { - ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", - atomic_read(&ah->intr_ref_cnt)); - return; - } - - __ath9k_hw_enable_interrupts(ah); -} -EXPORT_SYMBOL(ath9k_hw_resume_interrupts); - -void ath9k_hw_enable_interrupts(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - - if (!(ah->imask & ATH9K_INT_GLOBAL)) - return; - - if (!atomic_inc_and_test(&ah->intr_ref_cnt)) { - ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", - atomic_read(&ah->intr_ref_cnt)); - return; - } - - __ath9k_hw_enable_interrupts(ah); -} EXPORT_SYMBOL(ath9k_hw_enable_interrupts); void ath9k_hw_set_interrupts(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 1b63d26f30ce..7fbf7f965f61 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -748,7 +748,6 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah); void ath9k_hw_enable_interrupts(struct ath_hw *ah); void ath9k_hw_disable_interrupts(struct ath_hw *ah); void ath9k_hw_kill_interrupts(struct ath_hw *ah); -void ath9k_hw_resume_interrupts(struct ath_hw *ah); void ar9002_hw_attach_mac_ops(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3abc64574116..d184e682e636 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -373,20 +373,21 @@ void ath9k_tasklet(unsigned long data) struct ath_common *common = ath9k_hw_common(ah); enum ath_reset_type type; unsigned long flags; - u32 status; + u32 status = sc->intrstatus; u32 rxmask; - spin_lock_irqsave(&sc->intr_lock, flags); - status = sc->intrstatus; - sc->intrstatus = 0; - spin_unlock_irqrestore(&sc->intr_lock, flags); - ath9k_ps_wakeup(sc); spin_lock(&sc->sc_pcu_lock); if (status & ATH9K_INT_FATAL) { type = RESET_TYPE_FATAL_INT; ath9k_queue_reset(sc, type); + + /* + * Increment the ref. counter here so that + * interrupts are enabled in the reset routine. + */ + atomic_inc(&ah->intr_ref_cnt); ath_dbg(common, RESET, "FATAL: Skipping interrupts\n"); goto out; } @@ -402,6 +403,11 @@ void ath9k_tasklet(unsigned long data) type = RESET_TYPE_BB_WATCHDOG; ath9k_queue_reset(sc, type); + /* + * Increment the ref. counter here so that + * interrupts are enabled in the reset routine. + */ + atomic_inc(&ah->intr_ref_cnt); ath_dbg(common, RESET, "BB_WATCHDOG: Skipping interrupts\n"); goto out; @@ -414,6 +420,7 @@ void ath9k_tasklet(unsigned long data) if ((sc->gtt_cnt >= MAX_GTT_CNT) && !ath9k_hw_check_alive(ah)) { type = RESET_TYPE_TX_GTT; ath9k_queue_reset(sc, type); + atomic_inc(&ah->intr_ref_cnt); ath_dbg(common, RESET, "GTT: Skipping interrupts\n"); goto out; @@ -470,7 +477,7 @@ void ath9k_tasklet(unsigned long data) ath9k_btcoex_handle_interrupt(sc, status); /* re-enable hardware interrupt */ - ath9k_hw_resume_interrupts(ah); + ath9k_hw_enable_interrupts(ah); out: spin_unlock(&sc->sc_pcu_lock); ath9k_ps_restore(sc); @@ -534,9 +541,7 @@ irqreturn_t ath_isr(int irq, void *dev) return IRQ_NONE; /* Cache the status */ - spin_lock(&sc->intr_lock); - sc->intrstatus |= status; - spin_unlock(&sc->intr_lock); + sc->intrstatus = status; if (status & SCHED_INTR) sched = true; @@ -582,7 +587,7 @@ irqreturn_t ath_isr(int irq, void *dev) if (sched) { /* turn off every interrupt */ - ath9k_hw_kill_interrupts(ah); + ath9k_hw_disable_interrupts(ah); tasklet_schedule(&sc->intr_tq); } @@ -1545,13 +1550,13 @@ static int ath9k_sta_state(struct ieee80211_hw *hw, struct ath_common *common = ath9k_hw_common(sc->sc_ah); int ret = 0; - if (old_state == IEEE80211_STA_NOTEXIST && - new_state == IEEE80211_STA_NONE) { + if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC) { ret = ath9k_sta_add(hw, vif, sta); ath_dbg(common, CONFIG, "Add station: %pM\n", sta->addr); - } else if (old_state == IEEE80211_STA_NONE && - new_state == IEEE80211_STA_NOTEXIST) { + } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTH) { ret = ath9k_sta_remove(hw, vif, sta); ath_dbg(common, CONFIG, "Remove station: %pM\n", sta->addr); @@ -1855,16 +1860,14 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static int ath9k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); bool flush = false; int ret = 0; - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; mutex_lock(&sc->mutex); diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index ea7b8c25955f..7cdaf40c3057 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -27,6 +27,7 @@ static const struct pci_device_id ath_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ + { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ #ifdef CONFIG_ATH9K_PCOEM /* Mini PCI AR9220 MB92 cards: Compex WLM200NX, Wistron DNMA-92 */ @@ -37,7 +38,7 @@ static const struct pci_device_id ath_pci_id_table[] = { .driver_data = ATH9K_PCI_LED_ACT_HI }, #endif - { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ + { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ #ifdef CONFIG_ATH9K_PCOEM { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, @@ -85,11 +86,7 @@ static const struct pci_device_id ath_pci_id_table[] = { 0x10CF, /* Fujitsu */ 0x1536), .driver_data = ATH9K_PCI_D3_L1_WAR }, -#endif - { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ - -#ifdef CONFIG_ATH9K_PCOEM /* AR9285 card for Asus */ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, 0x002B, diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index 7ee1a3183a06..ac4781f37e78 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -180,9 +180,6 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, ssize_t len; int r; - if (count < 1) - return -EINVAL; - if (sc->cur_chan->nvifs > 1) return -EOPNOTSUPP; @@ -190,32 +187,25 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, if (copy_from_user(buf, user_buf, len)) return -EFAULT; - buf[len] = '\0'; - if (strtobool(buf, &start)) return -EINVAL; - mutex_lock(&sc->mutex); - if (start == sc->tx99_state) { if (!start) - goto out; + return count; ath_dbg(common, XMIT, "Resetting TX99\n"); ath9k_tx99_deinit(sc); } if (!start) { ath9k_tx99_deinit(sc); - goto out; + return count; } r = ath9k_tx99_init(sc); - if (r) { - mutex_unlock(&sc->mutex); + if (r) return r; - } -out: - mutex_unlock(&sc->mutex); + return count; } diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 4d1527a2e292..19d3d64416bf 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1413,12 +1413,10 @@ static void carl9170_ampdu_work(struct work_struct *work) static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; struct ar9170 *ar = hw->priv; struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; struct carl9170_sta_tid *tid_info; diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 62077bda8dde..06ea6cc9e30a 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -254,12 +254,8 @@ bool ath_is_49ghz_allowed(u16 regdomain) EXPORT_SYMBOL(ath_is_49ghz_allowed); /* Frequency is one where radar detection is required */ -static bool ath_is_radar_freq(u16 center_freq, - struct ath_regulatory *reg) - +static bool ath_is_radar_freq(u16 center_freq) { - if (reg->country_code == CTRY_INDIA) - return (center_freq >= 5500 && center_freq <= 5700); return (center_freq >= 5260 && center_freq <= 5700); } @@ -310,7 +306,7 @@ __ath_reg_apply_beaconing_flags(struct wiphy *wiphy, enum nl80211_reg_initiator initiator, struct ieee80211_channel *ch) { - if (ath_is_radar_freq(ch->center_freq, reg) || + if (ath_is_radar_freq(ch->center_freq) || (ch->flags & IEEE80211_CHAN_RADAR)) return; @@ -399,9 +395,8 @@ ath_reg_apply_ir_flags(struct wiphy *wiphy, } } -/* Always apply Radar/DFS rules on freq range 5500 MHz - 5700 MHz */ -static void ath_reg_apply_radar_flags(struct wiphy *wiphy, - struct ath_regulatory *reg) +/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */ +static void ath_reg_apply_radar_flags(struct wiphy *wiphy) { struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; @@ -414,7 +409,7 @@ static void ath_reg_apply_radar_flags(struct wiphy *wiphy, for (i = 0; i < sband->n_channels; i++) { ch = &sband->channels[i]; - if (!ath_is_radar_freq(ch->center_freq, reg)) + if (!ath_is_radar_freq(ch->center_freq)) continue; /* We always enable radar detection/DFS on this * frequency range. Additionally we also apply on @@ -510,7 +505,7 @@ void ath_reg_notifier_apply(struct wiphy *wiphy, struct ath_common *common = container_of(reg, struct ath_common, regulatory); /* We always apply this */ - ath_reg_apply_radar_flags(wiphy, reg); + ath_reg_apply_radar_flags(wiphy); /* * This would happen when we have sent a custom regulatory request @@ -658,7 +653,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, } wiphy_apply_custom_regulatory(wiphy, regd); - ath_reg_apply_radar_flags(wiphy, reg); + ath_reg_apply_radar_flags(wiphy); ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); return 0; } diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index 184b6810cde9..37f53bd8fcb1 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -68,14 +68,12 @@ enum CountryCode { CTRY_AUSTRALIA = 36, CTRY_AUSTRIA = 40, CTRY_AZERBAIJAN = 31, - CTRY_BAHAMAS = 44, CTRY_BAHRAIN = 48, CTRY_BANGLADESH = 50, CTRY_BARBADOS = 52, CTRY_BELARUS = 112, CTRY_BELGIUM = 56, CTRY_BELIZE = 84, - CTRY_BERMUDA = 60, CTRY_BOLIVIA = 68, CTRY_BOSNIA_HERZ = 70, CTRY_BRAZIL = 76, @@ -161,7 +159,6 @@ enum CountryCode { CTRY_ROMANIA = 642, CTRY_RUSSIA = 643, CTRY_SAUDI_ARABIA = 682, - CTRY_SERBIA = 688, CTRY_SERBIA_MONTENEGRO = 891, CTRY_SINGAPORE = 702, CTRY_SLOVAKIA = 703, @@ -173,13 +170,11 @@ enum CountryCode { CTRY_SWITZERLAND = 756, CTRY_SYRIA = 760, CTRY_TAIWAN = 158, - CTRY_TANZANIA = 834, CTRY_THAILAND = 764, CTRY_TRINIDAD_Y_TOBAGO = 780, CTRY_TUNISIA = 788, CTRY_TURKEY = 792, CTRY_UAE = 784, - CTRY_UGANDA = 800, CTRY_UKRAINE = 804, CTRY_UNITED_KINGDOM = 826, CTRY_UNITED_STATES = 840, diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index 15bbd1e0d912..bdd2b4d61f2f 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h @@ -35,7 +35,6 @@ enum EnumRd { FRANCE_RES = 0x31, FCC3_FCCA = 0x3A, FCC3_WORLD = 0x3B, - FCC3_ETSIC = 0x3F, ETSI1_WORLD = 0x37, ETSI3_ETSIA = 0x32, @@ -45,7 +44,6 @@ enum EnumRd { ETSI4_ETSIC = 0x38, ETSI5_WORLD = 0x39, ETSI6_WORLD = 0x34, - ETSI8_WORLD = 0x3D, ETSI_RESERVED = 0x33, MKK1_MKKA = 0x40, @@ -61,7 +59,6 @@ enum EnumRd { MKK1_MKKA1 = 0x4A, MKK1_MKKA2 = 0x4B, MKK1_MKKC = 0x4C, - APL2_FCCA = 0x4D, APL3_FCCA = 0x50, APL1_WORLD = 0x52, @@ -70,7 +67,6 @@ enum EnumRd { APL1_ETSIC = 0x55, APL2_ETSIC = 0x56, APL5_WORLD = 0x58, - APL13_WORLD = 0x5A, APL6_WORLD = 0x5B, APL7_FCCA = 0x5C, APL8_WORLD = 0x5D, @@ -172,7 +168,6 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {FCC2_ETSIC, CTL_FCC, CTL_ETSI}, {FCC3_FCCA, CTL_FCC, CTL_FCC}, {FCC3_WORLD, CTL_FCC, CTL_ETSI}, - {FCC3_ETSIC, CTL_FCC, CTL_ETSI}, {FCC4_FCCA, CTL_FCC, CTL_FCC}, {FCC5_FCCA, CTL_FCC, CTL_FCC}, {FCC6_FCCA, CTL_FCC, CTL_FCC}, @@ -184,7 +179,6 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {ETSI4_WORLD, CTL_ETSI, CTL_ETSI}, {ETSI5_WORLD, CTL_ETSI, CTL_ETSI}, {ETSI6_WORLD, CTL_ETSI, CTL_ETSI}, - {ETSI8_WORLD, CTL_ETSI, CTL_ETSI}, /* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */ {ETSI3_ETSIA, CTL_ETSI, CTL_ETSI}, @@ -194,11 +188,9 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {FCC1_FCCA, CTL_FCC, CTL_FCC}, {APL1_WORLD, CTL_FCC, CTL_ETSI}, {APL2_WORLD, CTL_FCC, CTL_ETSI}, - {APL2_FCCA, CTL_FCC, CTL_FCC}, {APL3_WORLD, CTL_FCC, CTL_ETSI}, {APL4_WORLD, CTL_FCC, CTL_ETSI}, {APL5_WORLD, CTL_FCC, CTL_ETSI}, - {APL13_WORLD, CTL_ETSI, CTL_ETSI}, {APL6_WORLD, CTL_ETSI, CTL_ETSI}, {APL8_WORLD, CTL_ETSI, CTL_ETSI}, {APL9_WORLD, CTL_ETSI, CTL_ETSI}, @@ -306,7 +298,6 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"}, {CTRY_AUSTRIA, ETSI1_WORLD, "AT"}, {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"}, - {CTRY_BAHAMAS, FCC3_WORLD, "BS"}, {CTRY_BAHRAIN, APL6_WORLD, "BH"}, {CTRY_BANGLADESH, NULL1_WORLD, "BD"}, {CTRY_BARBADOS, FCC2_WORLD, "BB"}, @@ -314,7 +305,6 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_BELGIUM, ETSI1_WORLD, "BE"}, {CTRY_BELGIUM2, ETSI4_WORLD, "BL"}, {CTRY_BELIZE, APL1_ETSIC, "BZ"}, - {CTRY_BERMUDA, FCC3_FCCA, "BM"}, {CTRY_BOLIVIA, APL1_ETSIC, "BO"}, {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"}, {CTRY_BRAZIL, FCC3_WORLD, "BR"}, @@ -454,7 +444,6 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_ROMANIA, NULL1_WORLD, "RO"}, {CTRY_RUSSIA, NULL1_WORLD, "RU"}, {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"}, - {CTRY_SERBIA, ETSI1_WORLD, "RS"}, {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"}, {CTRY_SINGAPORE, APL6_WORLD, "SG"}, {CTRY_SLOVAKIA, ETSI1_WORLD, "SK"}, @@ -466,12 +455,10 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_SWITZERLAND, ETSI1_WORLD, "CH"}, {CTRY_SYRIA, NULL1_WORLD, "SY"}, {CTRY_TAIWAN, APL3_FCCA, "TW"}, - {CTRY_TANZANIA, APL1_WORLD, "TZ"}, {CTRY_THAILAND, FCC3_WORLD, "TH"}, {CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT"}, {CTRY_TUNISIA, ETSI3_WORLD, "TN"}, {CTRY_TURKEY, ETSI3_WORLD, "TR"}, - {CTRY_UGANDA, FCC3_WORLD, "UG"}, {CTRY_UKRAINE, NULL1_WORLD, "UA"}, {CTRY_UAE, NULL1_WORLD, "AE"}, {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"}, diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index a27279c2c695..7c169abdbafe 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -857,14 +857,12 @@ static int wcn36xx_resume(struct ieee80211_hw *hw) static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu) { struct wcn36xx *wcn = hw->priv; struct wcn36xx_sta *sta_priv = NULL; - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", action, tid); diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index 99c21aac68bd..9bec8237231d 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c @@ -57,7 +57,7 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) RX_FLAG_MMIC_STRIPPED | RX_FLAG_DECRYPTED; - wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%llx\n", status.flag); + wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag); memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index f09fafaaaf1a..bb69a5949aea 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -125,15 +125,9 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, u32 *d = dst; const volatile u32 __iomem *s = src; - for (; count >= 4; count -= 4) + /* size_t is unsigned, if (count%4 != 0) it will wrap */ + for (count += 4; count > 4; count -= 4) *d++ = __raw_readl(s++); - - if (unlikely(count)) { - /* count can be 1..3 */ - u32 tmp = __raw_readl(s); - - memcpy(d, &tmp, count); - } } void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, @@ -142,16 +136,8 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, volatile u32 __iomem *d = dst; const u32 *s = src; - for (; count >= 4; count -= 4) + for (count += 4; count > 4; count -= 4) __raw_writel(*s++, d++); - - if (unlikely(count)) { - /* count can be 1..3 */ - u32 tmp = 0; - - memcpy(&tmp, s, count); - __raw_writel(tmp, d); - } } static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, @@ -344,19 +330,18 @@ static void wil_fw_error_worker(struct work_struct *work) wil->last_fw_recovery = jiffies; - wil_info(wil, "fw error recovery requested (try %d)...\n", - wil->recovery_count); - if (!no_fw_recovery) - wil->recovery_state = fw_recovery_running; - if (wil_wait_for_recovery(wil) != 0) - return; - mutex_lock(&wil->mutex); switch (wdev->iftype) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_MONITOR: - /* silent recovery, upper layers will see disconnect */ + wil_info(wil, "fw error recovery requested (try %d)...\n", + wil->recovery_count); + if (!no_fw_recovery) + wil->recovery_state = fw_recovery_running; + if (0 != wil_wait_for_recovery(wil)) + break; + __wil_down(wil); __wil_up(wil); break; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 91da67657f81..410a6645d316 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -726,10 +726,8 @@ int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev, return -ENOMEM; err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr, glom_skb); - if (err) { - brcmu_pkt_buf_free_skb(glom_skb); + if (err) goto done; - } skb_queue_walk(pktq, skb) { memcpy(skb->data, glom_skb->data, skb->len); @@ -1109,7 +1107,6 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43340), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362), - BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43364), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345), diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index ad35e760ed3f..deb5f78dcacc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -876,7 +876,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, eth_broadcast_addr(params_le->bssid); params_le->bss_type = DOT11_BSSTYPE_ANY; - params_le->scan_type = BRCMF_SCANTYPE_ACTIVE; + params_le->scan_type = 0; params_le->channel_num = 0; params_le->nprobes = cpu_to_le32(-1); params_le->active_time = cpu_to_le32(-1); @@ -884,9 +884,12 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, params_le->home_time = cpu_to_le32(-1); memset(¶ms_le->ssid_le, 0, sizeof(params_le->ssid_le)); + /* if request is null exit so it will be all channel broadcast scan */ + if (!request) + return; + n_ssids = request->n_ssids; n_channels = request->n_channels; - /* Copy channel array if applicable */ brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n", n_channels); @@ -923,8 +926,16 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, ptr += sizeof(ssid_le); } } else { - brcmf_dbg(SCAN, "Performing passive scan\n"); - params_le->scan_type = BRCMF_SCANTYPE_PASSIVE; + brcmf_dbg(SCAN, "Broadcast scan %p\n", request->ssids); + if ((request->ssids) && request->ssids->ssid_len) { + brcmf_dbg(SCAN, "SSID %s len=%d\n", + params_le->ssid_le.SSID, + request->ssids->ssid_len); + params_le->ssid_le.SSID_len = + cpu_to_le32(request->ssids->ssid_len); + memcpy(¶ms_le->ssid_le.SSID, request->ssids->ssid, + request->ssids->ssid_len); + } } /* Adding mask to channel numbers */ params_le->channel_num = @@ -2397,7 +2408,7 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) WL_BSS_INFO_MAX); if (err) { brcmf_err("Failed to get bss info (%d)\n", err); - goto out_kfree; + return; } si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period); @@ -2409,9 +2420,6 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; - -out_kfree: - kfree(buf); } static s32 @@ -2903,7 +2911,6 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, struct brcmf_cfg80211_info *cfg = ifp->drvr->config; s32 status; struct brcmf_escan_result_le *escan_result_le; - u32 escan_buflen; struct brcmf_bss_info_le *bss_info_le; struct brcmf_bss_info_le *bss = NULL; u32 bi_length; @@ -2920,23 +2927,11 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, if (status == BRCMF_E_STATUS_PARTIAL) { brcmf_dbg(SCAN, "ESCAN Partial result\n"); - if (e->datalen < sizeof(*escan_result_le)) { - brcmf_err("invalid event data length\n"); - goto exit; - } escan_result_le = (struct brcmf_escan_result_le *) data; if (!escan_result_le) { brcmf_err("Invalid escan result (NULL pointer)\n"); goto exit; } - escan_buflen = le32_to_cpu(escan_result_le->buflen); - if (escan_buflen > WL_ESCAN_BUF_SIZE || - escan_buflen > e->datalen || - escan_buflen < sizeof(*escan_result_le)) { - brcmf_err("Invalid escan buffer length: %d\n", - escan_buflen); - goto exit; - } if (le16_to_cpu(escan_result_le->bss_count) != 1) { brcmf_err("Invalid bss_count %d: ignoring\n", escan_result_le->bss_count); @@ -2953,8 +2948,9 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, } bi_length = le32_to_cpu(bss_info_le->length); - if (bi_length != escan_buflen - WL_ESCAN_RESULTS_FIXED_SIZE) { - brcmf_err("Ignoring invalid bss_info length: %d\n", + if (bi_length != (le32_to_cpu(escan_result_le->buflen) - + WL_ESCAN_RESULTS_FIXED_SIZE)) { + brcmf_err("Invalid bss_info length %d: ignoring\n", bi_length); goto exit; } @@ -4103,7 +4099,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, (u8 *)&settings->beacon.head[ie_offset], settings->beacon.head_len - ie_offset, WLAN_EID_SSID); - if (!ssid_ie || ssid_ie->len > IEEE80211_MAX_SSID_LEN) + if (!ssid_ie) return -EINVAL; memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len); @@ -4295,6 +4291,9 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); if (err < 0) brcmf_err("setting AP mode failed %d\n", err); + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0); + if (err < 0) + brcmf_err("setting INFRA mode failed %d\n", err); if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) brcmf_fil_iovar_int_set(ifp, "mbss", 0); err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, @@ -4470,11 +4469,6 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_KERNEL); } else if (ieee80211_is_action(mgmt->frame_control)) { - if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) { - brcmf_err("invalid action frame length\n"); - err = -EINVAL; - goto exit; - } af_params = kzalloc(sizeof(*af_params), GFP_KERNEL); if (af_params == NULL) { brcmf_err("unable to allocate frame\n"); @@ -6167,7 +6161,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, req->alpha2[0], req->alpha2[1]); /* ignore non-ISO3166 country codes */ - for (i = 0; i < 2; i++) + for (i = 0; i < sizeof(req->alpha2); i++) if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { brcmf_err("not a ISO3166 code\n"); return; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 82753e7c7e7c..b5ab98ee1445 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -211,7 +211,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, int ret; struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_pub *drvr = ifp->drvr; - struct ethhdr *eh; + struct ethhdr *eh = (struct ethhdr *)(skb->data); brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx); @@ -232,13 +232,22 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, goto done; } - /* Make sure there's enough writable headroom*/ - ret = skb_cow_head(skb, drvr->hdrlen); - if (ret < 0) { - brcmf_err("%s: skb_cow_head failed\n", + /* Make sure there's enough room for any header */ + if (skb_headroom(skb) < drvr->hdrlen) { + struct sk_buff *skb2; + + brcmf_dbg(INFO, "%s: insufficient headroom\n", brcmf_ifname(drvr, ifp->bssidx)); + drvr->bus_if->tx_realloc++; + skb2 = skb_realloc_headroom(skb, drvr->hdrlen); dev_kfree_skb(skb); - goto done; + skb = skb2; + if (skb == NULL) { + brcmf_err("%s: skb_realloc_headroom failed\n", + brcmf_ifname(drvr, ifp->bssidx)); + ret = -ENOMEM; + goto done; + } } /* validate length for ether packet */ @@ -248,8 +257,6 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, goto done; } - eh = (struct ethhdr *)(skb->data); - if (eh->h_proto == htons(ETH_P_PAE)) atomic_inc(&ifp->pend_8021x_cnt); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index 4320c4cae53e..daa427b46712 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h @@ -45,11 +45,6 @@ #define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff #define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 -/* scan type definitions */ -#define BRCMF_SCANTYPE_DEFAULT 0xFF -#define BRCMF_SCANTYPE_ACTIVE 0 -#define BRCMF_SCANTYPE_PASSIVE 1 - /* primary (ie tx) key */ #define BRCMF_PRIMARY_KEY (1 << 1) #define DOT11_BSSTYPE_ANY 2 diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 3196245ab820..d224b3dd72ed 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -461,23 +461,25 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) * @dev_addr: optional device address. * * P2P needs mac addresses for P2P device and interface. If no device - * address it specified, these are derived from a random ethernet - * address. + * address it specified, these are derived from the primary net device, ie. + * the permanent ethernet address of the device. */ static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr) { - bool random_addr = false; + struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; + bool local_admin = false; - if (!dev_addr || is_zero_ether_addr(dev_addr)) - random_addr = true; + if (!dev_addr || is_zero_ether_addr(dev_addr)) { + dev_addr = pri_ifp->mac_addr; + local_admin = true; + } - /* Generate the P2P Device Address obtaining a random ethernet - * address with the locally administered bit set. + /* Generate the P2P Device Address. This consists of the device's + * primary MAC address with the locally administered bit set. */ - if (random_addr) - eth_random_addr(p2p->dev_addr); - else - memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); + memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); + if (local_admin) + p2p->dev_addr[0] |= 0x02; /* Generate the P2P Interface Address. If the discovery and connection * BSSCFGs need to simultaneously co-exist, then this address must be diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index 35f62b00f1df..7e74ac3ad815 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c @@ -4291,13 +4291,6 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) brcmf_dbg(TRACE, "Enter\n"); if (bus) { - /* Stop watchdog task */ - if (bus->watchdog_tsk) { - send_sig(SIGTERM, bus->watchdog_tsk, 1); - kthread_stop(bus->watchdog_tsk); - bus->watchdog_tsk = NULL; - } - /* De-register interrupt handler */ brcmf_sdiod_intr_unregister(bus->sdiodev); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c index b7df576bb84d..796f5f9d5d5a 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c @@ -1079,10 +1079,8 @@ bool dma_rxfill(struct dma_pub *pub) pa = dma_map_single(di->dmadev, p->data, di->rxbufsize, DMA_FROM_DEVICE); - if (dma_mapping_error(di->dmadev, pa)) { - brcmu_pkt_buf_free_skb(p); + if (dma_mapping_error(di->dmadev, pa)) return false; - } /* save the free packet pointer */ di->rxp[rxout] = p; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 61ae2768132a..bec2dc1ca2e4 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -818,15 +818,13 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static int brcms_ops_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu) { struct brcms_info *wl = hw->priv; struct scb *scb = &wl->wlc->pri_scb; int status; - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u8 buf_size = params->buf_size; if (WARN_ON(scb->magic != SCB_MAGIC)) return -EIDRM; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index c75bfd3f8cb3..99dac9b8a082 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c @@ -14764,8 +14764,8 @@ static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi) } static void -wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, const u8 *events, - const u8 *dlys, u8 len) +wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys, + u8 len) { u32 t1_offset, t2_offset; u8 ctr; @@ -15240,16 +15240,16 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi) static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) { u16 currband; - static const s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 }; - const s8 *lna1_gain_db = NULL; - const s8 *lna1_gain_db_2 = NULL; - const s8 *lna2_gain_db = NULL; - static const s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 }; - const s8 *tia_gain_db; - static const s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 }; - const s8 *tia_gainbits; - static const u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f }; - const u16 *rfseq_init_gain; + s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 }; + s8 *lna1_gain_db = NULL; + s8 *lna1_gain_db_2 = NULL; + s8 *lna2_gain_db = NULL; + s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 }; + s8 *tia_gain_db; + s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 }; + s8 *tia_gainbits; + u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f }; + u16 *rfseq_init_gain; u16 init_gaincode; u16 clip1hi_gaincode; u16 clip1md_gaincode = 0; @@ -15310,9 +15310,10 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) if ((freq <= 5080) || (freq == 5825)) { - static const s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; - static const s8 lna1A_gain_db_2_rev7[] = { 11, 17, 22, 25}; - static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; + s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; + s8 lna1A_gain_db_2_rev7[] = { + 11, 17, 22, 25}; + s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; crsminu_th = 0x3e; lna1_gain_db = lna1A_gain_db_rev7; @@ -15320,9 +15321,10 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) lna2_gain_db = lna2A_gain_db_rev7; } else if ((freq >= 5500) && (freq <= 5700)) { - static const s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; - static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26}; - static const s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 }; + s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; + s8 lna1A_gain_db_2_rev7[] = { + 12, 18, 22, 26}; + s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 }; crsminu_th = 0x45; clip1md_gaincode_B = 0x14; @@ -15333,9 +15335,10 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) lna2_gain_db = lna2A_gain_db_rev7; } else { - static const s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; - static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26}; - static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; + s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; + s8 lna1A_gain_db_2_rev7[] = { + 12, 18, 22, 26}; + s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; crsminu_th = 0x41; lna1_gain_db = lna1A_gain_db_rev7; @@ -15447,65 +15450,65 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) NPHY_RFSEQ_CMD_CLR_HIQ_DIS, NPHY_RFSEQ_CMD_SET_HPF_BW }; - static const u8 rfseq_updategainu_dlys[] = { 10, 30, 1 }; - static const s8 lna1G_gain_db[] = { 7, 11, 16, 23 }; - static const s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 }; - static const s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 }; - static const s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 }; - static const s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 }; - static const s8 lna1A_gain_db[] = { 7, 11, 17, 23 }; - static const s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 }; - static const s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 }; - static const s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 }; - const s8 *lna1_gain_db = NULL; - static const s8 lna2G_gain_db[] = { -5, 6, 10, 14 }; - static const s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 }; - static const s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 }; - static const s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 }; - static const s8 lna2A_gain_db[] = { -6, 2, 6, 10 }; - static const s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 }; - static const s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 }; - static const s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 }; - const s8 *lna2_gain_db = NULL; - static const s8 tiaG_gain_db[] = { + u8 rfseq_updategainu_dlys[] = { 10, 30, 1 }; + s8 lna1G_gain_db[] = { 7, 11, 16, 23 }; + s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 }; + s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 }; + s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 }; + s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 }; + s8 lna1A_gain_db[] = { 7, 11, 17, 23 }; + s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 }; + s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 }; + s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 }; + s8 *lna1_gain_db = NULL; + s8 lna2G_gain_db[] = { -5, 6, 10, 14 }; + s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 }; + s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 }; + s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 }; + s8 lna2A_gain_db[] = { -6, 2, 6, 10 }; + s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 }; + s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 }; + s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 }; + s8 *lna2_gain_db = NULL; + s8 tiaG_gain_db[] = { 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A }; - static const s8 tiaA_gain_db[] = { + s8 tiaA_gain_db[] = { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 }; - static const s8 tiaA_gain_db_rev4[] = { + s8 tiaA_gain_db_rev4[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; - static const s8 tiaA_gain_db_rev5[] = { + s8 tiaA_gain_db_rev5[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; - static const s8 tiaA_gain_db_rev6[] = { + s8 tiaA_gain_db_rev6[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; - const s8 *tia_gain_db; - static const s8 tiaG_gainbits[] = { + s8 *tia_gain_db; + s8 tiaG_gainbits[] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; - static const s8 tiaA_gainbits[] = { + s8 tiaA_gainbits[] = { 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 }; - static const s8 tiaA_gainbits_rev4[] = { + s8 tiaA_gainbits_rev4[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; - static const s8 tiaA_gainbits_rev5[] = { + s8 tiaA_gainbits_rev5[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; - static const s8 tiaA_gainbits_rev6[] = { + s8 tiaA_gainbits_rev6[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; - const s8 *tia_gainbits; - static const s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 }; - static const s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 }; - static const u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f }; - static const u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f }; - static const u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f }; - static const u16 rfseqG_init_gain_rev5_elna[] = { + s8 *tia_gainbits; + s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 }; + s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 }; + u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f }; + u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f }; + u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f }; + u16 rfseqG_init_gain_rev5_elna[] = { 0x013f, 0x013f, 0x013f, 0x013f }; - static const u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f }; - static const u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f }; - static const u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f }; - static const u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f }; - static const u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f }; - static const u16 rfseqA_init_gain_rev4_elna[] = { + u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f }; + u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f }; + u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f }; + u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f }; + u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f }; + u16 rfseqA_init_gain_rev4_elna[] = { 0x314f, 0x314f, 0x314f, 0x314f }; - static const u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f }; - static const u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f }; - const u16 *rfseq_init_gain; + u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f }; + u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f }; + u16 *rfseq_init_gain; u16 initG_gaincode = 0x627e; u16 initG_gaincode_rev4 = 0x527e; u16 initG_gaincode_rev5 = 0x427e; @@ -15535,10 +15538,10 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) u16 clip1mdA_gaincode_rev6 = 0x2084; u16 clip1md_gaincode = 0; u16 clip1loG_gaincode = 0x0074; - static const u16 clip1loG_gaincode_rev5[] = { + u16 clip1loG_gaincode_rev5[] = { 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c }; - static const u16 clip1loG_gaincode_rev6[] = { + u16 clip1loG_gaincode_rev6[] = { 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e }; u16 clip1loG_gaincode_rev6_224B0 = 0x1074; @@ -16063,7 +16066,7 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) { - static const u8 rfseq_rx2tx_events[] = { + u8 rfseq_rx2tx_events[] = { NPHY_RFSEQ_CMD_NOP, NPHY_RFSEQ_CMD_RXG_FBW, NPHY_RFSEQ_CMD_TR_SWITCH, @@ -16073,7 +16076,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_RFSEQ_CMD_EXT_PA }; u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 }; - static const u8 rfseq_tx2rx_events[] = { + u8 rfseq_tx2rx_events[] = { NPHY_RFSEQ_CMD_NOP, NPHY_RFSEQ_CMD_EXT_PA, NPHY_RFSEQ_CMD_TX_GAIN, @@ -16082,8 +16085,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_RFSEQ_CMD_RXG_FBW, NPHY_RFSEQ_CMD_CLR_HIQ_DIS }; - static const u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; - static const u8 rfseq_tx2rx_events_rev3[] = { + u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; + u8 rfseq_tx2rx_events_rev3[] = { NPHY_REV3_RFSEQ_CMD_EXT_PA, NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_TX_GAIN, @@ -16093,7 +16096,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, NPHY_REV3_RFSEQ_CMD_END }; - static const u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; + u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; u8 rfseq_rx2tx_events_rev3[] = { NPHY_REV3_RFSEQ_CMD_NOP, NPHY_REV3_RFSEQ_CMD_RXG_FBW, @@ -16107,7 +16110,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) }; u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; - static const u8 rfseq_rx2tx_events_rev3_ipa[] = { + u8 rfseq_rx2tx_events_rev3_ipa[] = { NPHY_REV3_RFSEQ_CMD_NOP, NPHY_REV3_RFSEQ_CMD_RXG_FBW, NPHY_REV3_RFSEQ_CMD_TR_SWITCH, @@ -16118,15 +16121,15 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_END }; - static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; - static const u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; + u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; + u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; s16 alpha0, alpha1, alpha2; s16 beta0, beta1, beta2; u32 leg_data_weights, ht_data_weights, nss1_data_weights, stbc_data_weights; u8 chan_freq_range = 0; - static const u16 dac_control = 0x0002; + u16 dac_control = 0x0002; u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 }; u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 }; u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 }; @@ -16136,8 +16139,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 }; u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 }; u16 *aux_adc_gain; - static const u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; - static const u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; + u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; + u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; s32 min_nvar_val = 0x18d; s32 min_nvar_offset_6mbps = 20; u8 pdetrange; @@ -16148,9 +16151,9 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77; u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77; u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77; - static const u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 }; - static const u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; - static const u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; + u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 }; + u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; + u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; u16 ipalvlshift_3p3_war_en = 0; u16 rccal_bcap_val, rccal_scap_val; u16 rccal_tx20_11b_bcap = 0; @@ -24288,13 +24291,13 @@ static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core) u16 bbmult; u16 tblentry; - static const struct nphy_txiqcal_ladder ladder_lo[] = { + struct nphy_txiqcal_ladder ladder_lo[] = { {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5}, {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7} }; - static const struct nphy_txiqcal_ladder ladder_iq[] = { + struct nphy_txiqcal_ladder ladder_iq[] = { {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1}, {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7} @@ -25770,67 +25773,67 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, u16 cal_gain[2]; struct nphy_iqcal_params cal_params[2]; u32 tbl_len; - const void *tbl_ptr; + void *tbl_ptr; bool ladder_updated[2]; u8 mphase_cal_lastphase = 0; int bcmerror = 0; bool phyhang_avoid_state = false; - static const u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { + u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { 0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901, 0x1902, 0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607, 0x6407 }; - static const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { + u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { 0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400, 0x3200, 0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406, 0x6407 }; - static const u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { + u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { 0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201, 0x1202, 0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207, 0x4707 }; - static const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { + u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { 0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900, 0x2300, 0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706, 0x4707 }; - static const u16 tbl_tx_iqlo_cal_startcoefs[] = { + u16 tbl_tx_iqlo_cal_startcoefs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; - static const u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { + u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { 0x8123, 0x8264, 0x8086, 0x8245, 0x8056, 0x9123, 0x9264, 0x9086, 0x9245, 0x9056 }; - static const u16 tbl_tx_iqlo_cal_cmds_recal[] = { + u16 tbl_tx_iqlo_cal_cmds_recal[] = { 0x8101, 0x8253, 0x8053, 0x8234, 0x8034, 0x9101, 0x9253, 0x9053, 0x9234, 0x9034 }; - static const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { + u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; - static const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { + u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234, 0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234 }; - static const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { + u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { 0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223, 0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223 }; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/stf.c b/drivers/net/wireless/brcm80211/brcmsmac/stf.c index 0ab865de1491..dd9162722495 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/stf.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.c @@ -87,7 +87,7 @@ void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel, u16 chanspec) { - struct tx_power power = { }; + struct tx_power power; u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id; /* Clear previous settings */ diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index 63f95e9c2992..a740083634d8 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -446,7 +446,8 @@ static int cw1200_spi_disconnect(struct spi_device *func) return 0; } -static int __maybe_unused cw1200_spi_suspend(struct device *dev) +#ifdef CONFIG_PM +static int cw1200_spi_suspend(struct device *dev) { struct hwbus_priv *self = spi_get_drvdata(to_spi_device(dev)); @@ -459,12 +460,16 @@ static int __maybe_unused cw1200_spi_suspend(struct device *dev) static SIMPLE_DEV_PM_OPS(cw1200_pm_ops, cw1200_spi_suspend, NULL); +#endif + static struct spi_driver spi_driver = { .probe = cw1200_spi_probe, .remove = cw1200_spi_disconnect, .driver = { .name = "cw1200_wlan_spi", - .pm = IS_ENABLED(CONFIG_PM) ? &cw1200_pm_ops : NULL, +#ifdef CONFIG_PM + .pm = &cw1200_pm_ops, +#endif }, }; diff --git a/drivers/net/wireless/cw1200/pm.h b/drivers/net/wireless/cw1200/pm.h index 534548470ebc..3ed90ff22bb8 100644 --- a/drivers/net/wireless/cw1200/pm.h +++ b/drivers/net/wireless/cw1200/pm.h @@ -31,18 +31,13 @@ int cw1200_pm_init(struct cw1200_pm_state *pm, void cw1200_pm_deinit(struct cw1200_pm_state *pm); int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); -int cw1200_can_suspend(struct cw1200_common *priv); int cw1200_wow_resume(struct ieee80211_hw *hw); +int cw1200_can_suspend(struct cw1200_common *priv); void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, unsigned long tmo); #else static inline void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, - unsigned long tmo) -{ -} -static inline int cw1200_can_suspend(struct cw1200_common *priv) -{ - return 0; + unsigned long tmo) { } #endif #endif diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c index c602a1e674ca..95a7fdb3cc1c 100644 --- a/drivers/net/wireless/cw1200/sta.c +++ b/drivers/net/wireless/cw1200/sta.c @@ -2135,7 +2135,9 @@ void cw1200_mcast_timeout(unsigned long arg) int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu) { /* Aggregation is implemented fully in firmware, * including block ack negotiation. Do not allow diff --git a/drivers/net/wireless/cw1200/sta.h b/drivers/net/wireless/cw1200/sta.h index a0bacaa39b31..bebb3379017f 100644 --- a/drivers/net/wireless/cw1200/sta.h +++ b/drivers/net/wireless/cw1200/sta.h @@ -109,7 +109,9 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev, u32 changed); int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params); + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu); void cw1200_suspend_resume(struct cw1200_common *priv, struct wsm_suspend_resume *arg); diff --git a/drivers/net/wireless/cw1200/wsm.c b/drivers/net/wireless/cw1200/wsm.c index 3dd46c78c1cc..9e0ca3048657 100644 --- a/drivers/net/wireless/cw1200/wsm.c +++ b/drivers/net/wireless/cw1200/wsm.c @@ -379,6 +379,7 @@ static int wsm_multi_tx_confirm(struct cw1200_common *priv, { int ret; int count; + int i; count = WSM_GET32(buf); if (WARN_ON(count <= 0)) @@ -394,10 +395,11 @@ static int wsm_multi_tx_confirm(struct cw1200_common *priv, } cw1200_debug_txed_multi(priv, count); - do { + for (i = 0; i < count; ++i) { ret = wsm_tx_confirm(priv, buf, link_id); - } while (!ret && --count); - + if (ret) + return ret; + } return ret; underflow: diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 515aa3f993f3..6df3ee561d52 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -836,30 +836,25 @@ static int hfa384x_get_rid(struct net_device *dev, u16 rid, void *buf, int len, spin_lock_bh(&local->baplock); res = hfa384x_setup_bap(dev, BAP0, rid, 0); - if (res) - goto unlock; - - res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec)); - if (res) - goto unlock; + if (!res) + res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec)); if (le16_to_cpu(rec.len) == 0) { /* RID not available */ res = -ENODATA; - goto unlock; } rlen = (le16_to_cpu(rec.len) - 1) * 2; - if (exact_len && rlen != len) { + if (!res && exact_len && rlen != len) { printk(KERN_DEBUG "%s: hfa384x_get_rid - RID len mismatch: " "rid=0x%04x, len=%d (expected %d)\n", dev->name, rid, rlen, len); res = -ENODATA; } - res = hfa384x_from_bap(dev, BAP0, buf, len); + if (!res) + res = hfa384x_from_bap(dev, BAP0, buf, len); -unlock: spin_unlock_bh(&local->baplock); mutex_unlock(&local->rid_bap_mtx); diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index ae047ab7a4df..93bdf684babe 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -1019,13 +1019,12 @@ il3945_hw_txq_ctx_free(struct il_priv *il) int txq_id; /* Tx queues */ - if (il->txq) { + if (il->txq) for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) if (txq_id == IL39_CMD_QUEUE_NUM) il_cmd_queue_free(il); else il_tx_queue_free(il, txq_id); - } /* free tx queue structure */ il_free_txq_mem(il); diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 04b0349a6ad9..6656215a13a9 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5982,14 +5982,12 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 * ssn, + u8 buf_size, bool amsdu) { struct il_priv *il = hw->priv; int ret = -EINVAL; - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; D_HT("A-MPDU action on addr %pM tid %d\n", sta->addr, tid); diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index e432715e02d8..8ab8706f9422 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h @@ -182,7 +182,9 @@ void il4965_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params); + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 * ssn, + u8 buf_size, bool amsdu); int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c index c148085742a0..20e6aa910700 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.c +++ b/drivers/net/wireless/iwlwifi/dvm/calib.c @@ -901,7 +901,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, /* bound gain by 2 bits value max, 3rd bit is sign */ data->delta_gain_code[i] = min(abs(delta_g), - (s32) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); + (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); if (delta_g < 0) /* diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 1eb1a823a111..b3ad34e8bf5a 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -729,15 +729,12 @@ static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg) static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); int ret = -EINVAL; - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; - u8 buf_size = params->buf_size; struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 95b82cc132e6..d82984912e04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -73,7 +73,6 @@ /* NVM offsets (in words) definitions */ enum wkp_nvm_offsets { /* NVM HW-Section offset (in words) definitions */ - SUBSYSTEM_ID = 0x0A, HW_ADDR = 0x15, /* NVM SW-Section offset (in words) definitions */ @@ -258,12 +257,13 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, const __le16 * const nvm_ch_flags, - bool lar_supported, bool no_wide_in_5ghz) + bool lar_supported) { int ch_idx; int n_channels = 0; struct ieee80211_channel *channel; u16 ch_flags; + bool is_5ghz; int num_of_ch, num_2ghz_channels; const u8 *nvm_chan; @@ -278,20 +278,12 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, } for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { - bool is_5ghz = (ch_idx >= num_2ghz_channels); - ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); - if (is_5ghz && !data->sku_cap_band_52GHz_enable) + if (ch_idx >= num_2ghz_channels && + !data->sku_cap_band_52GHz_enable) continue; - /* workaround to disable wide channels in 5GHz */ - if (no_wide_in_5ghz && is_5ghz) { - ch_flags &= ~(NVM_CHANNEL_40MHZ | - NVM_CHANNEL_80MHZ | - NVM_CHANNEL_160MHZ); - } - if (!lar_supported && !(ch_flags & NVM_CHANNEL_VALID)) { /* * Channels might become valid later if lar is @@ -311,8 +303,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, n_channels++; channel->hw_value = nvm_chan[ch_idx]; - channel->band = is_5ghz ? - IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; + channel->band = (ch_idx < num_2ghz_channels) ? + IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; channel->center_freq = ieee80211_channel_to_frequency( channel->hw_value, channel->band); @@ -324,6 +316,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, * is not used in mvm, and is used for backwards compatibility */ channel->max_power = IWL_DEFAULT_MAX_TX_POWER; + is_5ghz = channel->band == IEEE80211_BAND_5GHZ; /* don't put limitations in case we're using LAR */ if (!lar_supported) @@ -412,8 +405,7 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, const __le16 *ch_section, - u8 tx_chains, u8 rx_chains, bool lar_supported, - bool no_wide_in_5ghz) + u8 tx_chains, u8 rx_chains, bool lar_supported) { int n_channels; int n_used = 0; @@ -422,14 +414,12 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, if (cfg->device_family != IWL_DEVICE_FAMILY_8000) n_channels = iwl_init_channel_map( dev, cfg, data, - &ch_section[NVM_CHANNELS], lar_supported, - no_wide_in_5ghz); + &ch_section[NVM_CHANNELS], lar_supported); else n_channels = iwl_init_channel_map( dev, cfg, data, &ch_section[NVM_CHANNELS_FAMILY_8000], - lar_supported, - no_wide_in_5ghz); + lar_supported); sband = &data->bands[IEEE80211_BAND_2GHZ]; sband->band = IEEE80211_BAND_2GHZ; @@ -592,39 +582,6 @@ static void iwl_set_hw_address_family_8000(struct device *dev, #define IWL_4165_DEVICE_ID 0x5501 -static bool -iwl_nvm_no_wide_in_5ghz(struct device *dev, const struct iwl_cfg *cfg, - const __le16 *nvm_hw) -{ - /* - * Workaround a bug in Indonesia SKUs where the regulatory in - * some 7000-family OTPs erroneously allow wide channels in - * 5GHz. To check for Indonesia, we take the SKU value from - * bits 1-4 in the subsystem ID and check if it is either 5 or - * 9. In those cases, we need to force-disable wide channels - * in 5GHz otherwise the FW will throw a sysassert when we try - * to use them. - */ - if (cfg->device_family == IWL_DEVICE_FAMILY_7000) { - /* - * Unlike the other sections in the NVM, the hw - * section uses big-endian. - */ - u16 subsystem_id = be16_to_cpup((const __be16 *)nvm_hw - + SUBSYSTEM_ID); - u8 sku = (subsystem_id & 0x1e) >> 1; - - if (sku == 5 || sku == 9) { - IWL_DEBUG_EEPROM(dev, - "disabling wide channels in 5GHz (0x%0x %d)\n", - subsystem_id, sku); - return true; - } - } - - return false; -} - struct iwl_nvm_data * iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_hw, const __le16 *nvm_sw, @@ -634,7 +591,6 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, u32 mac_addr0, u32 mac_addr1, u32 hw_id) { struct iwl_nvm_data *data; - bool no_wide_in_5ghz = iwl_nvm_no_wide_in_5ghz(dev, cfg, nvm_hw); u32 sku; u32 radio_cfg; u16 lar_config; @@ -701,8 +657,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, iwl_set_hw_address(cfg, data, nvm_hw); iwl_init_sbands(dev, cfg, data, nvm_sw, - tx_chains, rx_chains, lar_fw_supported, - no_wide_in_5ghz); + tx_chains, rx_chains, lar_fw_supported); } else { u16 lar_offset = data->nvm_version < 0xE39 ? NVM_LAR_OFFSET_FAMILY_8000_OLD : @@ -718,8 +673,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, iwl_init_sbands(dev, cfg, data, regulatory, tx_chains, rx_chains, - lar_fw_supported && data->lar_enabled, - no_wide_in_5ghz); + lar_fw_supported && data->lar_enabled); } data->calib_version = 255; diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 9584f950fd2f..610c442c7ab2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c @@ -935,8 +935,7 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id) } mvm->fw_dbg_conf = conf_id; - - return 0; + return ret; } static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 984cd2f05c4a..f96ab2f4b90e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -826,16 +826,13 @@ iwl_mvm_ampdu_check_trigger(struct iwl_mvm *mvm, struct ieee80211_vif *vif, static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, + u16 *ssn, u8 buf_size, bool amsdu) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; bool tx_agg_ref = false; - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; - u8 buf_size = params->buf_size; IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n", sta->addr, tid, action); @@ -1906,11 +1903,6 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, struct iwl_mvm_mc_iter_data *data = _data; struct iwl_mvm *mvm = data->mvm; struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd; - struct iwl_host_cmd hcmd = { - .id = MCAST_FILTER_CMD, - .flags = CMD_ASYNC, - .dataflags[0] = IWL_HCMD_DFL_NOCOPY, - }; int ret, len; /* if we don't have free ports, mcast frames will be dropped */ @@ -1925,10 +1917,7 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4); - hcmd.len[0] = len; - hcmd.data[0] = cmd; - - ret = iwl_mvm_send_cmd(mvm, &hcmd); + ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd); if (ret) IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret); } @@ -4003,8 +3992,8 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx, if (idx != 0) return -ENOENT; - if (!fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS)) + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS)) return -ENOENT; mutex_lock(&mvm->mutex); @@ -4050,8 +4039,8 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw, struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - if (!fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS)) + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS)) return; /* if beacon filtering isn't on mac80211 does it anyway */ diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c index d7d72adb6343..b0f59fdd287c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/iwlwifi/mvm/sf.c @@ -215,7 +215,7 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, enum iwl_sf_state new_state) { struct iwl_sf_cfg_cmd sf_cmd = { - .state = cpu_to_le32(new_state), + .state = cpu_to_le32(SF_FULL_ON), }; struct ieee80211_sta *sta; int ret = 0; diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index f7e6a09926dd..d58c094f2f04 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -475,64 +475,48 @@ static const struct pci_device_id iwl_hw_card_ids[] = { MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); #ifdef CONFIG_ACPI -#define ACPI_SPLC_METHOD "SPLC" -#define ACPI_SPLC_DOMAIN_WIFI (0x07) +#define SPL_METHOD "SPLC" +#define SPL_DOMAINTYPE_MODULE BIT(0) +#define SPL_DOMAINTYPE_WIFI BIT(1) +#define SPL_DOMAINTYPE_WIGIG BIT(2) +#define SPL_DOMAINTYPE_RFEM BIT(3) -static u64 splc_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splc) +static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx) { - union acpi_object *data_pkg, *dflt_pwr_limit; - int i; - - /* We need at least two elements, one for the revision and one - * for the data itself. Also check that the revision is - * supported (currently only revision 0). - */ - if (splc->type != ACPI_TYPE_PACKAGE || - splc->package.count < 2 || - splc->package.elements[0].type != ACPI_TYPE_INTEGER || - splc->package.elements[0].integer.value != 0) { - IWL_DEBUG_INFO(trans, - "Unsupported structure returned by the SPLC method. Ignoring.\n"); + union acpi_object *limits, *domain_type, *power_limit; + + if (splx->type != ACPI_TYPE_PACKAGE || + splx->package.count != 2 || + splx->package.elements[0].type != ACPI_TYPE_INTEGER || + splx->package.elements[0].integer.value != 0) { + IWL_ERR(trans, "Unsupported splx structure\n"); return 0; } - /* loop through all the packages to find the one for WiFi */ - for (i = 1; i < splc->package.count; i++) { - union acpi_object *domain; - - data_pkg = &splc->package.elements[i]; - - /* Skip anything that is not a package with the right - * amount of elements (i.e. at least 2 integers). - */ - if (data_pkg->type != ACPI_TYPE_PACKAGE || - data_pkg->package.count < 2 || - data_pkg->package.elements[0].type != ACPI_TYPE_INTEGER || - data_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) - continue; - - domain = &data_pkg->package.elements[0]; - if (domain->integer.value == ACPI_SPLC_DOMAIN_WIFI) - break; - - data_pkg = NULL; + limits = &splx->package.elements[1]; + if (limits->type != ACPI_TYPE_PACKAGE || + limits->package.count < 2 || + limits->package.elements[0].type != ACPI_TYPE_INTEGER || + limits->package.elements[1].type != ACPI_TYPE_INTEGER) { + IWL_ERR(trans, "Invalid limits element\n"); + return 0; } - if (!data_pkg) { - IWL_DEBUG_INFO(trans, - "No element for the WiFi domain returned by the SPLC method.\n"); + domain_type = &limits->package.elements[0]; + power_limit = &limits->package.elements[1]; + if (!(domain_type->integer.value & SPL_DOMAINTYPE_WIFI)) { + IWL_DEBUG_INFO(trans, "WiFi power is not limited\n"); return 0; } - dflt_pwr_limit = &data_pkg->package.elements[1]; - return dflt_pwr_limit->integer.value; + return power_limit->integer.value; } static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev) { acpi_handle pxsx_handle; acpi_handle handle; - struct acpi_buffer splc = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_buffer splx = {ACPI_ALLOCATE_BUFFER, NULL}; acpi_status status; pxsx_handle = ACPI_HANDLE(&pdev->dev); @@ -543,24 +527,23 @@ static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev) } /* Get the method's handle */ - status = acpi_get_handle(pxsx_handle, (acpi_string)ACPI_SPLC_METHOD, - &handle); + status = acpi_get_handle(pxsx_handle, (acpi_string)SPL_METHOD, &handle); if (ACPI_FAILURE(status)) { - IWL_DEBUG_INFO(trans, "SPLC method not found\n"); + IWL_DEBUG_INFO(trans, "SPL method not found\n"); return; } /* Call SPLC with no arguments */ - status = acpi_evaluate_object(handle, NULL, NULL, &splc); + status = acpi_evaluate_object(handle, NULL, NULL, &splx); if (ACPI_FAILURE(status)) { IWL_ERR(trans, "SPLC invocation failed (0x%x)\n", status); return; } - trans->dflt_pwr_limit = splc_get_pwr_limit(trans, splc.pointer); + trans->dflt_pwr_limit = splx_get_pwr_limit(trans, splx.pointer); IWL_DEBUG_INFO(trans, "Default power limit set to %lld\n", trans->dflt_pwr_limit); - kfree(splc.pointer); + kfree(splx.pointer); } #else /* CONFIG_ACPI */ diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index d6f9858ff2de..e06591f625c4 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -713,8 +713,6 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) WQ_HIGHPRI | WQ_UNBOUND, 1); INIT_WORK(&rba->rx_alloc, iwl_pcie_rx_allocator_work); - cancel_work_sync(&rba->rx_alloc); - spin_lock(&rba->lock); atomic_set(&rba->req_pending, 0); atomic_set(&rba->req_ready, 0); diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 8dfe6b2bc703..a8c8a4a7420b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -1508,9 +1508,9 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, /* start the TFD with the scratchbuf */ scratch_size = min_t(int, copy_size, IWL_HCMD_SCRATCHBUF_SIZE); - memcpy(&txq->scratchbufs[idx], &out_cmd->hdr, scratch_size); + memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size); iwl_pcie_txq_build_tfd(trans, txq, - iwl_pcie_get_scratchbuf_dma(txq, idx), + iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr), scratch_size, true); /* map first command fragment, if any remains */ diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e8b770a95f7a..c00a7daaa4bc 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -699,21 +699,16 @@ static int hwsim_fops_ps_write(void *dat, u64 val) val != PS_MANUAL_POLL) return -EINVAL; - if (val == PS_MANUAL_POLL) { - if (data->ps != PS_ENABLED) - return -EINVAL; - local_bh_disable(); - ieee80211_iterate_active_interfaces_atomic( - data->hw, IEEE80211_IFACE_ITER_NORMAL, - hwsim_send_ps_poll, data); - local_bh_enable(); - return 0; - } old_ps = data->ps; data->ps = val; local_bh_disable(); - if (old_ps == PS_DISABLED && val != PS_DISABLED) { + if (val == PS_MANUAL_POLL) { + ieee80211_iterate_active_interfaces_atomic( + data->hw, IEEE80211_IFACE_ITER_NORMAL, + hwsim_send_ps_poll, data); + data->ps_poll_pending = true; + } else if (old_ps == PS_DISABLED && val != PS_DISABLED) { ieee80211_iterate_active_interfaces_atomic( data->hw, IEEE80211_IFACE_ITER_NORMAL, hwsim_send_nullfunc_ps, data); @@ -1822,12 +1817,10 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu) { - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - switch (action) { case IEEE80211_AMPDU_TX_START: ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -2544,7 +2537,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, tasklet_hrtimer_init(&data->beacon_timer, mac80211_hwsim_beacon, - CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS); spin_lock_bh(&hwsim_radio_lock); list_add_tail(&data->list, &hwsim_radios); @@ -2730,7 +2723,6 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] || !info->attrs[HWSIM_ATTR_FLAGS] || !info->attrs[HWSIM_ATTR_COOKIE] || - !info->attrs[HWSIM_ATTR_SIGNAL] || !info->attrs[HWSIM_ATTR_TX_INFO]) goto out; @@ -2889,8 +2881,6 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2, static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) { struct hwsim_new_radio_params param = { 0 }; - const char *hwname = NULL; - int ret; param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; @@ -2904,14 +2894,8 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) if (info->attrs[HWSIM_ATTR_NO_VIF]) param.no_vif = true; - if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { - hwname = kasprintf(GFP_KERNEL, "%.*s", - nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]), - (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME])); - if (!hwname) - return -ENOMEM; - param.hwname = hwname; - } + if (info->attrs[HWSIM_ATTR_RADIO_NAME]) + param.hwname = nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); if (info->attrs[HWSIM_ATTR_USE_CHANCTX]) param.use_chanctx = true; @@ -2925,16 +2909,12 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) { u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]); - if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) { - kfree(hwname); + if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) return -EINVAL; - } param.regd = hwsim_world_regdom_custom[idx]; } - ret = mac80211_hwsim_new_radio(info, ¶m); - kfree(hwname); - return ret; + return mac80211_hwsim_new_radio(info, ¶m); } static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) @@ -2943,15 +2923,11 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) s64 idx = -1; const char *hwname = NULL; - if (info->attrs[HWSIM_ATTR_RADIO_ID]) { + if (info->attrs[HWSIM_ATTR_RADIO_ID]) idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); - } else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { - hwname = kasprintf(GFP_KERNEL, "%.*s", - nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]), - (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME])); - if (!hwname) - return -ENOMEM; - } else + else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) + hwname = (void *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); + else return -EINVAL; spin_lock_bh(&hwsim_radio_lock); @@ -2960,8 +2936,7 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) if (data->idx != idx) continue; } else { - if (!hwname || - strcmp(hwname, wiphy_name(data->hw->wiphy))) + if (strcmp(hwname, wiphy_name(data->hw->wiphy))) continue; } @@ -2969,12 +2944,10 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) spin_unlock_bh(&hwsim_radio_lock); mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), info); - kfree(hwname); return 0; } spin_unlock_bh(&hwsim_radio_lock); - kfree(hwname); return -ENODEV; } diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c index e70dd9523911..f715eee39851 100644 --- a/drivers/net/wireless/mediatek/mt7601u/main.c +++ b/drivers/net/wireless/mediatek/mt7601u/main.c @@ -334,13 +334,11 @@ static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value) static int mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, + bool amsdu) { struct mt7601u_dev *dev = hw->priv; - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; WARN_ON(msta->wcid.idx > GROUP_WCID(0)); diff --git a/drivers/net/wireless/mediatek/mt7601u/mcu.c b/drivers/net/wireless/mediatek/mt7601u/mcu.c index 686b1b5dd394..fbb1986eda3c 100644 --- a/drivers/net/wireless/mediatek/mt7601u/mcu.c +++ b/drivers/net/wireless/mediatek/mt7601u/mcu.c @@ -66,10 +66,8 @@ mt7601u_mcu_msg_alloc(struct mt7601u_dev *dev, const void *data, int len) WARN_ON(len % 4); /* if length is not divisible by 4 we need to pad */ skb = alloc_skb(len + MT_DMA_HDR_LEN + 4, GFP_KERNEL); - if (skb) { - skb_reserve(skb, MT_DMA_HDR_LEN); - memcpy(skb_put(skb, len), data, len); - } + skb_reserve(skb, MT_DMA_HDR_LEN); + memcpy(skb_put(skb, len), data, len); return skb; } @@ -172,8 +170,6 @@ static int mt7601u_mcu_function_select(struct mt7601u_dev *dev, }; skb = mt7601u_mcu_msg_alloc(dev, &msg, sizeof(msg)); - if (!skb) - return -ENOMEM; return mt7601u_mcu_msg_send(dev, skb, CMD_FUN_SET_OP, func == 5); } @@ -209,8 +205,6 @@ mt7601u_mcu_calibrate(struct mt7601u_dev *dev, enum mcu_calibrate cal, u32 val) }; skb = mt7601u_mcu_msg_alloc(dev, &msg, sizeof(msg)); - if (!skb) - return -ENOMEM; return mt7601u_mcu_msg_send(dev, skb, CMD_CALIBRATION_OP, true); } diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 49f3e17c28ea..aa498e0d2204 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -101,6 +101,13 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, { struct txpd *local_tx_pd; struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); + unsigned int pad; + int headroom = (priv->adapter->iface_type == + MWIFIEX_USB) ? 0 : INTF_HEADER_LEN; + + pad = ((void *)skb->data - sizeof(*local_tx_pd) - + headroom - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1); + skb_push(skb, pad); skb_push(skb, sizeof(*local_tx_pd)); @@ -114,10 +121,12 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, local_tx_pd->bss_num = priv->bss_num; local_tx_pd->bss_type = priv->bss_type; /* Always zero as the data is followed by struct txpd */ - local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); + local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) + + pad); local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU); local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len - - sizeof(*local_tx_pd)); + sizeof(*local_tx_pd) - + pad); if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET; @@ -181,11 +190,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, ra_list_flags); return -1; } - - /* skb_aggr->data already 64 byte align, just reserve bus interface - * header and txpd. - */ - skb_reserve(skb_aggr, headroom + sizeof(struct txpd)); + skb_reserve(skb_aggr, MWIFIEX_MIN_DATA_HEADER_LEN); tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr); memset(tx_info_aggr, 0, sizeof(*tx_info_aggr)); diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 9a8982f581c5..4073116e6e9f 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -2144,9 +2144,8 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, is_scanning_required = 1; } else { mwifiex_dbg(priv->adapter, MSG, - "info: trying to associate to '%.*s' bssid %pM\n", - req_ssid.ssid_len, (char *)req_ssid.ssid, - bss->bssid); + "info: trying to associate to '%s' bssid %pM\n", + (char *)req_ssid.ssid, bss->bssid); memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN); break; } @@ -2203,8 +2202,8 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, } mwifiex_dbg(adapter, INFO, - "info: Trying to associate to %.*s and bssid %pM\n", - (int)sme->ssid_len, (char *)sme->ssid, sme->bssid); + "info: Trying to associate to %s and bssid %pM\n", + (char *)sme->ssid, sme->bssid); ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, priv->bss_mode, sme->channel, sme, 0); @@ -2334,8 +2333,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, } mwifiex_dbg(priv->adapter, MSG, - "info: trying to join to %.*s and bssid %pM\n", - params->ssid_len, (char *)params->ssid, params->bssid); + "info: trying to join to %s and bssid %pM\n", + (char *)params->ssid, params->bssid); mwifiex_set_ibss_params(priv, params); @@ -3740,7 +3739,7 @@ int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter) if (adapter->config_bands & BAND_A) n_channels_a = mwifiex_band_5ghz.n_channels; - adapter->num_in_chan_stats = n_channels_bg + n_channels_a; + adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a); adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) * adapter->num_in_chan_stats); diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 45d97b64ef84..9824d8dd2b44 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -115,8 +115,7 @@ mwifiex_info_read(struct file *file, char __user *ubuf, if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { p += sprintf(p, "multicast_count=\"%d\"\n", netdev_mc_count(netdev)); - p += sprintf(p, "essid=\"%.*s\"\n", info.ssid.ssid_len, - info.ssid.ssid); + p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); p += sprintf(p, "bssid=\"%pM\"\n", info.bssid); p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); p += sprintf(p, "country_code = \"%s\"\n", info.country_code); diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 6378dfd3b4e8..3cda1f956f0b 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -661,9 +661,10 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN, sizeof(priv->assoc_rsp_buf)); - assoc_rsp->a_id = cpu_to_le16(aid); memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); + assoc_rsp->a_id = cpu_to_le16(aid); + if (status_code) { priv->adapter->dbg.num_cmd_assoc_failure++; mwifiex_dbg(priv->adapter, ERROR, diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 268e50ba88a5..21192b6f9c64 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -947,7 +947,6 @@ static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) if (card && card->cmd_buf) { mwifiex_unmap_pci_memory(adapter, card->cmd_buf, PCI_DMA_TODEVICE); - dev_kfree_skb_any(card->cmd_buf); } return 0; } @@ -1514,11 +1513,6 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) return -1; card->cmd_buf = skb; - /* - * Need to keep a reference, since core driver might free up this - * buffer before we've unmapped it. - */ - skb_get(skb); /* To send a command, the driver will: 1. Write the 64bit physical address of the data buffer to @@ -1616,7 +1610,6 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) if (card->cmd_buf) { mwifiex_unmap_pci_memory(adapter, card->cmd_buf, PCI_DMA_TODEVICE); - dev_kfree_skb_any(card->cmd_buf); card->cmd_buf = NULL; } diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index fb98f42cb5e7..c20017ced566 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -2170,12 +2170,6 @@ mwifiex_update_chan_statistics(struct mwifiex_private *priv, sizeof(struct mwifiex_chan_stats); for (i = 0 ; i < num_chan; i++) { - if (adapter->survey_idx >= adapter->num_in_chan_stats) { - mwifiex_dbg(adapter, WARN, - "FW reported too many channel results (max %d)\n", - adapter->num_in_chan_stats); - return; - } chan_stats.chan_num = fw_chan_stats->chan_num; chan_stats.bandcfg = fw_chan_stats->bandcfg; chan_stats.flags = fw_chan_stats->flags; diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 6cfa2969b123..d6c4f0f60839 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -1098,6 +1098,8 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, encrypt_key.is_rx_seq_valid = true; } } else { + if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) + return 0; encrypt_key.key_disable = true; if (mac_addr) memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 1a1b1de87583..e43aff932360 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -624,9 +624,6 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf) MWIFIEX_FUNC_SHUTDOWN); } - if (adapter->workqueue) - flush_workqueue(adapter->workqueue); - mwifiex_usb_free(card); mwifiex_dbg(adapter, FATAL, diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index eb5ffa5b1c6c..0cec8a64473e 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c @@ -702,14 +702,12 @@ void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr, s8 nflr) { struct mwifiex_histogram_data *phist_data = priv->hist_data; - s8 nf = -nflr; - s8 rssi = snr - nflr; atomic_inc(&phist_data->num_samples); atomic_inc(&phist_data->rx_rate[rx_rate]); - atomic_inc(&phist_data->snr[snr + 128]); - atomic_inc(&phist_data->noise_flr[nf + 128]); - atomic_inc(&phist_data->sig_str[rssi + 128]); + atomic_inc(&phist_data->snr[snr]); + atomic_inc(&phist_data->noise_flr[128 + nflr]); + atomic_inc(&phist_data->sig_str[nflr - snr]); } /* function to reset histogram data during init/reset */ diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 088429d0a634..30e3aaae32e2 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -5421,13 +5421,11 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx, static int mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu) { - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; - u8 buf_size = params->buf_size; + int i, rc = 0; struct mwl8k_priv *priv = hw->priv; struct mwl8k_ampdu_stream *stream; diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index 4ac6764f4897..257a9eadd595 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -488,7 +488,7 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell) entry += sizeof(__le16); chan->pa_points_per_curve = 8; - memset(chan->curve_data, 0, sizeof(chan->curve_data)); + memset(chan->curve_data, 0, sizeof(*chan->curve_data)); memcpy(chan->curve_data, entry, sizeof(struct p54_pa_curve_data_sample) * min((u8)8, curve_data->points_per_channel)); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index c78abfc7bd96..0881ba8535f4 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -247,10 +247,7 @@ static const UCHAR b4_default_startup_parms[] = { 0x04, 0x08, /* Noise gain, limit offset */ 0x28, 0x28, /* det rssi, med busy offsets */ 7, /* det sync thresh */ - 0, 2, 2, /* test mode, min, max */ - 0, /* rx/tx delay */ - 0, 0, 0, 0, 0, 0, /* current BSS id */ - 0 /* hop set */ + 0, 2, 2 /* test mode, min, max */ }; /*===========================================================================*/ @@ -601,7 +598,7 @@ static void init_startup_params(ray_dev_t *local) * a_beacon_period = hops a_beacon_period = KuS *//* 64ms = 010000 */ if (local->fw_ver == 0x55) { - memcpy(&local->sparm.b4, b4_default_startup_parms, + memcpy((UCHAR *) &local->sparm.b4, b4_default_startup_parms, sizeof(struct b4_startup_params)); /* Translate sane kus input values to old build 4/5 format */ /* i = hop time in uS truncated to 3 bytes */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c index b3691712df61..b7f72f9c7988 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c @@ -1454,7 +1454,6 @@ static int rtl8187_probe(struct usb_interface *intf, goto err_free_dev; } mutex_init(&priv->io_mutex); - mutex_init(&priv->conf_mutex); SET_IEEE80211_DEV(dev, &intf->dev); usb_set_intfdata(intf, dev); @@ -1628,6 +1627,7 @@ static int rtl8187_probe(struct usb_interface *intf, printk(KERN_ERR "rtl8187: Cannot register device\n"); goto err_free_dmabuf; } + mutex_init(&priv->conf_mutex); skb_queue_head_init(&priv->b_tx_status.queue); wiphy_info(dev->wiphy, "hwaddr %pM, %s V%d + %s, rfkill mask %d\n", diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 7d820c395375..6aed923a709a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -5375,13 +5375,13 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static int rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, + bool amsdu) { struct rtl8xxxu_priv *priv = hw->priv; struct device *dev = &priv->udev->dev; u8 ampdu_factor, ampdu_density; - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; switch (action) { case IEEE80211_AMPDU_TX_START: diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index aab752328c26..7a40d8dffa36 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -1303,13 +1303,12 @@ EXPORT_SYMBOL_GPL(rtl_action_proc); static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc) { - struct ieee80211_hw *hw = rtlpriv->hw; - rtlpriv->ra.is_special_data = true; if (rtlpriv->cfg->ops->get_btc_status()) rtlpriv->btcoexist.btc_ops->btc_special_packet_notify( rtlpriv, 1); - rtl_lps_leave(hw); + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } @@ -1382,7 +1381,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx, if (is_tx) { rtlpriv->ra.is_special_data = true; - rtl_lps_leave(hw); + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 8006f0972ad1..c925a4dff599 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -135,6 +135,7 @@ static void rtl_fw_do_work(const struct firmware *firmware, void *context, firmware->size); rtlpriv->rtlhal.wowlan_fwsize = firmware->size; } + rtlpriv->rtlhal.fwsize = firmware->size; release_firmware(firmware); } @@ -1152,8 +1153,10 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, } else { mstatus = RT_MEDIA_DISCONNECT; - if (mac->link_state == MAC80211_LINKED) - rtl_lps_leave(hw); + if (mac->link_state == MAC80211_LINKED) { + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + } if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); mac->link_state = MAC80211_NOLINK; @@ -1368,13 +1371,11 @@ static void rtl_op_sta_notify(struct ieee80211_hw *hw, static int rtl_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; switch (action) { case IEEE80211_AMPDU_TX_START: @@ -1431,7 +1432,8 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw, } if (mac->link_state == MAC80211_LINKED) { - rtl_lps_leave(hw); + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); mac->link_state = MAC80211_LINKED_SCANNING; } else { rtl_ips_nic_on(hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index b51815eccdb3..5b4048041147 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -664,9 +664,11 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) } if (((rtlpriv->link_info.num_rx_inperiod + - rtlpriv->link_info.num_tx_inperiod) > 8) || - (rtlpriv->link_info.num_rx_inperiod > 2)) - rtl_lps_leave(hw); + rtlpriv->link_info.num_tx_inperiod) > 8) || + (rtlpriv->link_info.num_rx_inperiod > 2)) { + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + } } static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw, @@ -917,8 +919,10 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) } if (((rtlpriv->link_info.num_rx_inperiod + rtlpriv->link_info.num_tx_inperiod) > 8) || - (rtlpriv->link_info.num_rx_inperiod > 2)) - rtl_lps_leave(hw); + (rtlpriv->link_info.num_rx_inperiod > 2)) { + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + } skb = new_skb; no_new: if (rtlpriv->use_new_trx_flow) { @@ -1572,14 +1576,7 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) dev_kfree_skb_irq(skb); ring->idx = (ring->idx + 1) % ring->entries; } - - if (rtlpriv->use_new_trx_flow) { - rtlpci->tx_ring[i].cur_tx_rp = 0; - rtlpci->tx_ring[i].cur_tx_wp = 0; - } - ring->idx = 0; - ring->entries = rtlpci->txringcount[i]; } } spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); @@ -2276,7 +2273,7 @@ int rtl_pci_probe(struct pci_dev *pdev, /* find adapter */ if (!_rtl_pci_find_adapter(pdev, hw)) { err = -ENODEV; - goto fail2; + goto fail3; } /* Init IO handler */ @@ -2346,10 +2343,10 @@ int rtl_pci_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, NULL); rtl_deinit_core(hw); -fail2: if (rtlpriv->io.pci_mem_start != 0) pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); +fail2: pci_release_regions(pdev); complete(&rtlpriv->firmware_loading_complete); diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h index 672f81ea02d0..5da6703942d9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.h +++ b/drivers/net/wireless/realtek/rtlwifi/pci.h @@ -275,10 +275,10 @@ struct mp_adapter { }; struct rtl_pci_priv { - struct bt_coexist_info bt_coexist; - struct rtl_led_ctl ledctl; struct rtl_pci dev; struct mp_adapter ndis_adapter; + struct rtl_led_ctl ledctl; + struct bt_coexist_info bt_coexist; }; #define rtl_pcipriv(hw) (((struct rtl_pci_priv *)(rtl_priv(hw))->priv)) diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c index 626ff300352b..b69321d45f04 100644 --- a/drivers/net/wireless/realtek/rtlwifi/ps.c +++ b/drivers/net/wireless/realtek/rtlwifi/ps.c @@ -414,8 +414,8 @@ void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) } } -/* Interrupt safe routine to enter the leisure power save mode.*/ -static void rtl_lps_enter_core(struct ieee80211_hw *hw) +/*Enter the leisure power save mode.*/ +void rtl_lps_enter(struct ieee80211_hw *hw) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); @@ -455,9 +455,10 @@ static void rtl_lps_enter_core(struct ieee80211_hw *hw) spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); } +EXPORT_SYMBOL(rtl_lps_enter); -/* Interrupt safe routine to leave the leisure power save mode.*/ -static void rtl_lps_leave_core(struct ieee80211_hw *hw) +/*Leave the leisure power save mode.*/ +void rtl_lps_leave(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); @@ -487,6 +488,7 @@ static void rtl_lps_leave_core(struct ieee80211_hw *hw) } spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); } +EXPORT_SYMBOL(rtl_lps_leave); /* For sw LPS*/ void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) @@ -679,34 +681,12 @@ void rtl_lps_change_work_callback(struct work_struct *work) struct rtl_priv *rtlpriv = rtl_priv(hw); if (rtlpriv->enter_ps) - rtl_lps_enter_core(hw); + rtl_lps_enter(hw); else - rtl_lps_leave_core(hw); + rtl_lps_leave(hw); } EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback); -void rtl_lps_enter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (!in_interrupt()) - return rtl_lps_enter_core(hw); - rtlpriv->enter_ps = true; - schedule_work(&rtlpriv->works.lps_change_work); -} -EXPORT_SYMBOL_GPL(rtl_lps_enter); - -void rtl_lps_leave(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (!in_interrupt()) - return rtl_lps_leave_core(hw); - rtlpriv->enter_ps = false; - schedule_work(&rtlpriv->works.lps_change_work); -} -EXPORT_SYMBOL_GPL(rtl_lps_leave); - void rtl_swlps_wq_callback(void *data) { struct rtl_works *rtlworks = container_of_dwork_rtl(data, diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c index f67e7e5b13e1..5be34118e0af 100644 --- a/drivers/net/wireless/realtek/rtlwifi/regd.c +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c @@ -345,9 +345,9 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select( return &rtl_regdom_no_midband; case COUNTRY_CODE_IC: return &rtl_regdom_11; + case COUNTRY_CODE_ETSI: case COUNTRY_CODE_TELEC_NETGEAR: return &rtl_regdom_60_64; - case COUNTRY_CODE_ETSI: case COUNTRY_CODE_SPAIN: case COUNTRY_CODE_FRANCE: case COUNTRY_CODE_ISRAEL: @@ -406,8 +406,6 @@ static u8 channel_plan_to_country_code(u8 channelplan) return COUNTRY_CODE_WORLD_WIDE_13; case 0x22: return COUNTRY_CODE_IC; - case 0x25: - return COUNTRY_CODE_ETSI; case 0x32: return COUNTRY_CODE_TELEC_NETGEAR; case 0x41: diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c index c2a156a8acec..5624ade92cc0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c @@ -304,6 +304,9 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, writeVal = 0x00000000; if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) writeVal = writeVal - 0x06060606; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_BT2) + writeVal = writeVal; *(p_outwriteval + rf) = writeVal; } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c index 1c69e8140d9d..0708eedd9671 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c @@ -664,7 +664,7 @@ void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct sk_buff *skb = NULL; - bool rtstatus; + u32 totalpacketlen; u8 u1rsvdpageloc[5] = { 0 }; bool b_dlok = false; @@ -727,9 +727,7 @@ void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) memcpy((u8 *)skb_put(skb, totalpacketlen), &reserved_page_packet, totalpacketlen); - rtstatus = rtl_cmd_send_packet(hw, skb); - if (rtstatus) - b_dlok = true; + b_dlok = true; if (b_dlok) { RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c index b1601441991d..5f14308e8eb3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c @@ -1003,7 +1003,7 @@ static void _rtl92ee_hw_configure(struct ieee80211_hw *hw) rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x100a); /* Note Data sheet don't define */ - rtl_write_byte(rtlpriv, 0x4C7, 0x80); + rtl_write_word(rtlpriv, 0x4C7, 0x80); rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c index 89515f02c353..5a3df9198ddf 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c @@ -1123,8 +1123,7 @@ static void _rtl8723be_enable_aspm_back_door(struct ieee80211_hw *hw) /* Configuration Space offset 0x70f BIT7 is used to control L0S */ tmp8 = _rtl8723be_dbi_read(rtlpriv, 0x70f); - _rtl8723be_dbi_write(rtlpriv, 0x70f, tmp8 | BIT(7) | - ASPM_L1_LATENCY << 3); + _rtl8723be_dbi_write(rtlpriv, 0x70f, tmp8 | BIT(7)); /* Configuration Space offset 0x719 Bit3 is for L1 * BIT4 is for clock request diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c index 7b13962ec9da..b57cfd965196 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c @@ -2488,9 +2488,9 @@ void rtl8821ae_dm_txpower_tracking_callback_thermalmeter( for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p]; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n", - rtldm->thermalvalue, thermal_value); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n", + rtldm->thermalvalue, thermal_value); /*Record last Power Tracking Thermal Value*/ rtldm->thermalvalue = thermal_value; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index 348ed1b0e58b..bbb789f8990b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c @@ -1127,7 +1127,7 @@ static u8 _rtl8821ae_dbi_read(struct rtl_priv *rtlpriv, u16 addr) } if (0 == tmp) { read_addr = REG_DBI_RDATA + addr % 4; - ret = rtl_read_byte(rtlpriv, read_addr); + ret = rtl_read_word(rtlpriv, read_addr); } return ret; } @@ -1169,8 +1169,7 @@ static void _rtl8821ae_enable_aspm_back_door(struct ieee80211_hw *hw) } tmp = _rtl8821ae_dbi_read(rtlpriv, 0x70f); - _rtl8821ae_dbi_write(rtlpriv, 0x70f, tmp | BIT(7) | - ASPM_L1_LATENCY << 3); + _rtl8821ae_dbi_write(rtlpriv, 0x70f, tmp | BIT(7)); tmp = _rtl8821ae_dbi_read(rtlpriv, 0x719); _rtl8821ae_dbi_write(rtlpriv, 0x719, tmp | BIT(3) | BIT(4)); @@ -1378,7 +1377,6 @@ static void _rtl8821ae_get_wakeup_reason(struct ieee80211_hw *hw) ppsc->wakeup_reason = 0; - do_gettimeofday(&ts); rtlhal->last_suspend_sec = ts.tv_sec; switch (fw_reason) { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c index 4b354918e183..9b4d8a637915 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c @@ -359,107 +359,6 @@ bool rtl8821ae_phy_rf_config(struct ieee80211_hw *hw) return rtl8821ae_phy_rf6052_config(hw); } -static void _rtl8812ae_phy_set_rfe_reg_24g(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp; - - switch (rtlhal->rfe_type) { - case 3: - rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x54337770); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x54337770); - rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); - rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); - rtl_set_bbreg(hw, 0x900, 0x00000303, 0x1); - break; - case 4: - rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77777777); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777); - rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x001); - rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x001); - break; - case 5: - rtl_write_byte(rtlpriv, RA_RFE_PINMUX + 2, 0x77); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777); - tmp = rtl_read_byte(rtlpriv, RA_RFE_INV + 3); - rtl_write_byte(rtlpriv, RA_RFE_INV + 3, tmp & ~0x1); - rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); - break; - case 1: - if (rtlpriv->btcoexist.bt_coexistence) { - rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xffffff, 0x777777); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, - 0x77777777); - rtl_set_bbreg(hw, RA_RFE_INV, 0x33f00000, 0x000); - rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); - break; - } - case 0: - case 2: - default: - rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77777777); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777); - rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x000); - rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); - break; - } -} - -static void _rtl8812ae_phy_set_rfe_reg_5g(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp; - - switch (rtlhal->rfe_type) { - case 0: - rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77337717); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337717); - rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); - rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); - break; - case 1: - if (rtlpriv->btcoexist.bt_coexistence) { - rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xffffff, 0x337717); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, - 0x77337717); - rtl_set_bbreg(hw, RA_RFE_INV, 0x33f00000, 0x000); - rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); - } else { - rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, - 0x77337717); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, - 0x77337717); - rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x000); - rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); - } - break; - case 3: - rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x54337717); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x54337717); - rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); - rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); - rtl_set_bbreg(hw, 0x900, 0x00000303, 0x1); - break; - case 5: - rtl_write_byte(rtlpriv, RA_RFE_PINMUX + 2, 0x33); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337777); - tmp = rtl_read_byte(rtlpriv, RA_RFE_INV + 3); - rtl_write_byte(rtlpriv, RA_RFE_INV + 3, tmp | 0x1); - rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); - break; - case 2: - case 4: - default: - rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77337777); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337777); - rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); - rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); - break; - } -} - u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, u8 rf_path) { @@ -654,9 +553,14 @@ void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) /* 0x82C[1:0] = 2b'00 */ rtl_set_bbreg(hw, 0x82c, 0x3, 0); } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - _rtl8812ae_phy_set_rfe_reg_24g(hw); + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, + 0x77777777); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, + 0x77777777); + rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x000); + rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x000); + } rtl_set_bbreg(hw, RTXPATH, 0xf0, 0x1); rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0x1); @@ -711,8 +615,14 @@ void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) /* 0x82C[1:0] = 2'b00 */ rtl_set_bbreg(hw, 0x82c, 0x3, 1); - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - _rtl8812ae_phy_set_rfe_reg_5g(hw); + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, + 0x77337777); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, + 0x77337777); + rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x010); + rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x010); + } rtl_set_bbreg(hw, RTXPATH, 0xf0, 0); rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0xf); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h index ed69dbe178ff..1d6110f9c1fb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h @@ -2424,7 +2424,6 @@ #define BMASKH4BITS 0xf0000000 #define BMASKOFDM_D 0xffc00000 #define BMASKCCK 0x3f3f3f3f -#define BMASKRFEINV 0x3ff00000 #define BRFREGOFFSETMASK 0xfffff diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index ad8390d2997b..aac1ed3f7bb4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -834,30 +834,12 @@ static void rtl_usb_stop(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - struct urb *urb; /* should after adapter start and interrupt enable. */ set_hal_stop(rtlhal); cancel_work_sync(&rtlpriv->works.fill_h2c_cmd); /* Enable software */ SET_USB_STOP(rtlusb); - - /* free pre-allocated URBs from rtl_usb_start() */ - usb_kill_anchored_urbs(&rtlusb->rx_submitted); - - tasklet_kill(&rtlusb->rx_work_tasklet); - cancel_work_sync(&rtlpriv->works.lps_change_work); - - flush_workqueue(rtlpriv->works.rtl_wq); - - skb_queue_purge(&rtlusb->rx_queue); - - while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) { - usb_free_coherent(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); - usb_free_urb(urb); - } - rtlpriv->cfg->ops->hw_disable(hw); } @@ -1091,7 +1073,6 @@ int rtl_usb_probe(struct usb_interface *intf, return -ENOMEM; } rtlpriv = hw->priv; - rtlpriv->hw = hw; rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32), GFP_KERNEL); if (!rtlpriv->usb_data) diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h index 441c4412130c..685273ca9561 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.h +++ b/drivers/net/wireless/realtek/rtlwifi/usb.h @@ -150,9 +150,8 @@ struct rtl_usb { }; struct rtl_usb_priv { - struct bt_coexist_info bt_coexist; - struct rtl_led_ctl ledctl; struct rtl_usb dev; + struct rtl_led_ctl ledctl; }; #define rtl_usbpriv(hw) (((struct rtl_usb_priv *)(rtl_priv(hw))->priv)) diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index d676d055feda..b6faf624480e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -99,7 +99,6 @@ #define RTL_USB_MAX_RX_COUNT 100 #define QBSS_LOAD_SIZE 5 #define MAX_WMMELE_LENGTH 64 -#define ASPM_L1_LATENCY 7 #define TOTAL_CAM_ENTRY 32 diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 259590013382..a13d1f2b5912 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -3425,10 +3425,6 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf) /* because rndis_command() sleeps we need to use workqueue */ priv->workqueue = create_singlethread_workqueue("rndis_wlan"); - if (!priv->workqueue) { - wiphy_free(wiphy); - return -ENOMEM; - } INIT_WORK(&priv->work, rndis_wlan_worker); INIT_DELAYED_WORK(&priv->dev_poller_work, rndis_device_poller); INIT_DELAYED_WORK(&priv->scan_work, rndis_get_scan_results); diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 4df992de7d07..b5bcc933a2a6 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -659,24 +659,29 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, * informs the f/w regarding this. * @hw: Pointer to the ieee80211_hw structure. * @vif: Pointer to the ieee80211_vif structure. - * @params: Pointer to A-MPDU action parameters + * @action: ieee80211_ampdu_mlme_action enum. + * @sta: Pointer to the ieee80211_sta structure. + * @tid: Traffic identifier. + * @ssn: Pointer to ssn value. + * @buf_size: Buffer size (for kernel version > 2.6.38). + * @amsdu: is AMSDU in AMPDU allowed * * Return: status: 0 on success, negative error code on failure. */ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, + unsigned short tid, + unsigned short *ssn, + unsigned char buf_size, + bool amsdu) { int status = -EOPNOTSUPP; struct rsi_hw *adapter = hw->priv; struct rsi_common *common = adapter->priv; u16 seq_no = 0; u8 ii = 0; - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; - u8 buf_size = params->buf_size; for (ii = 0; ii < RSI_MAX_VIFS; ii++) { if (vif == adapter->vifs[ii]) diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index fc895b466ebb..8428858204a6 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -155,6 +155,7 @@ static void rsi_reset_card(struct sdio_func *pfunction) int err; struct mmc_card *card = pfunction->card; struct mmc_host *host = card->host; + s32 bit = (fls(host->ocr_avail) - 1); u8 cmd52_resp; u32 clock, resp, i; u16 rca; @@ -174,6 +175,7 @@ static void rsi_reset_card(struct sdio_func *pfunction) msleep(20); /* Initialize the SDIO card */ + host->ios.vdd = bit; host->ios.chip_select = MMC_CS_DONTCARE; host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; host->ios.power_mode = MMC_POWER_UP; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 69c1c09687a3..9733b31a780d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -7935,11 +7935,10 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) EXPORT_SYMBOL_GPL(rt2800_get_tsf); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu) { - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv; int ret = 0; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 83f1a44fb9b4..440790b92b19 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -218,7 +218,9 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, const struct ieee80211_tx_queue_params *params); u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params); + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu); int rt2800_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 869411f55d88..cd4777954f87 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c @@ -1196,7 +1196,8 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); enable = bss_conf->arp_addr_cnt == 1 && bss_conf->assoc; - ret = wl1251_acx_arp_ip_filter(wl, enable, addr); + wl1251_acx_arp_ip_filter(wl, enable, addr); + if (ret < 0) goto out_sleep; } @@ -1566,7 +1567,6 @@ struct ieee80211_hw *wl1251_alloc_hw(void) wl->state = WL1251_STATE_OFF; mutex_init(&wl->mutex); - spin_lock_init(&wl->wl_lock); wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE; wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE; diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c index 085ef5c87262..09c7e098f460 100644 --- a/drivers/net/wireless/ti/wl18xx/event.c +++ b/drivers/net/wireless/ti/wl18xx/event.c @@ -206,33 +206,5 @@ int wl18xx_process_mailbox_events(struct wl1271 *wl) mbox->sc_pwd_len, mbox->sc_pwd); - if (vector & RX_BA_WIN_SIZE_CHANGE_EVENT_ID) { - struct wl12xx_vif *wlvif; - struct ieee80211_vif *vif; - struct ieee80211_sta *sta; - u8 link_id = mbox->rx_ba_link_id; - u8 win_size = mbox->rx_ba_win_size; - const u8 *addr; - - wlvif = wl->links[link_id].wlvif; - vif = wl12xx_wlvif_to_vif(wlvif); - - /* Update RX aggregation window size and call - * MAC routine to stop active RX aggregations for this link - */ - if (wlvif->bss_type != BSS_TYPE_AP_BSS) - addr = vif->bss_conf.bssid; - else - addr = wl->links[link_id].addr; - - sta = ieee80211_find_sta(vif, addr); - if (sta) { - sta->max_rx_aggregation_subframes = win_size; - ieee80211_stop_rx_ba_session(vif, - wl->links[link_id].ba_bitmap, - addr); - } - } - return 0; } diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h index 9495fadc8093..f3d4f13379cb 100644 --- a/drivers/net/wireless/ti/wl18xx/event.h +++ b/drivers/net/wireless/ti/wl18xx/event.h @@ -38,7 +38,6 @@ enum { REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(18), DFS_CHANNELS_CONFIG_COMPLETE_EVENT = BIT(19), PERIODIC_SCAN_REPORT_EVENT_ID = BIT(20), - RX_BA_WIN_SIZE_CHANGE_EVENT_ID = BIT(21), SMART_CONFIG_SYNC_EVENT_ID = BIT(22), SMART_CONFIG_DECODE_EVENT_ID = BIT(23), TIME_SYNC_EVENT_ID = BIT(24), diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 47f355e92193..50cce42089a5 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1029,8 +1029,7 @@ static int wl18xx_boot(struct wl1271 *wl) DFS_CHANNELS_CONFIG_COMPLETE_EVENT | SMART_CONFIG_SYNC_EVENT_ID | SMART_CONFIG_DECODE_EVENT_ID | - TIME_SYNC_EVENT_ID | - RX_BA_WIN_SIZE_CHANGE_EVENT_ID; + TIME_SYNC_EVENT_ID; wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID; diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index 0646c9b6f8d7..f28fa3b5029d 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c @@ -1419,8 +1419,7 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, /* setup BA session receiver setting in the FW. */ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, - u16 ssn, bool enable, u8 peer_hlid, - u8 win_size) + u16 ssn, bool enable, u8 peer_hlid) { struct wl1271_acx_ba_receiver_setup *acx; int ret; @@ -1436,7 +1435,7 @@ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, acx->hlid = peer_hlid; acx->tid = tid_index; acx->enable = enable; - acx->win_size = win_size; + acx->win_size = wl->conf.ht.rx_ba_win_size; acx->ssn = ssn; ret = wlcore_cmd_configure_failsafe(wl, ACX_BA_SESSION_RX_SETUP, acx, diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index 524aea495dff..954d57ec98f4 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h @@ -1112,8 +1112,7 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl, int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, - u16 ssn, bool enable, u8 peer_hlid, - u8 win_size); + u16 ssn, bool enable, u8 peer_hlid); int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif, u64 *mactime); int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 7b27c7e23af2..ec7f6af3fab2 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5261,16 +5261,14 @@ static int wl12xx_op_sta_state(struct ieee80211_hw *hw, static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu) { struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; u8 hlid, *ba_bitmap; - struct ieee80211_sta *sta = params->sta; - enum ieee80211_ampdu_mlme_action action = params->action; - u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action, tid); @@ -5328,9 +5326,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, } ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true, - hlid, - params->buf_size); - + hlid); if (!ret) { *ba_bitmap |= BIT(tid); wl->ba_rx_session_count++; @@ -5351,7 +5347,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, } ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false, - hlid, 0); + hlid); if (!ret) { *ba_bitmap &= ~BIT(tid); wl->ba_rx_session_count--; diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index e4a8280cea83..c172da56b550 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -388,11 +388,6 @@ static int wl1271_suspend(struct device *dev) mmc_pm_flag_t sdio_flags; int ret = 0; - if (!wl) { - dev_err(dev, "no wilink module was probed\n"); - goto out; - } - dev_dbg(dev, "wl1271 suspend. wow_enabled: %d\n", wl->wow_enabled); diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 9ebe00ea8f81..44f059f7f34e 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -71,7 +71,7 @@ * only support SPI for 12xx - this code should be reworked when 18xx * support is introduced */ -#define SPI_AGGR_BUFFER_SIZE (4 * SZ_4K) +#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) /* Maximum number of SPI write chunks */ #define WSPI_MAX_NUM_OF_CHUNKS \ diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 34173b5e886f..0333ab0fd926 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -201,7 +201,6 @@ struct xenvif_queue { /* Per-queue data for xenvif */ unsigned long remaining_credit; struct timer_list credit_timeout; u64 credit_window_start; - bool rate_limited; /* Statistics */ struct xenvif_stats stats; diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 60b26f32d31d..e7bd63eb2876 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -105,11 +105,7 @@ static int xenvif_poll(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete(napi); - /* If the queue is rate-limited, it shall be - * rescheduled in the timer callback. - */ - if (likely(!queue->rate_limited)) - xenvif_napi_schedule_or_enable_events(queue); + xenvif_napi_schedule_or_enable_events(queue); } return work_done; diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 02db20b26749..1049c34e7d43 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -67,7 +67,6 @@ module_param(rx_drain_timeout_msecs, uint, 0444); unsigned int rx_stall_timeout_msecs = 60000; module_param(rx_stall_timeout_msecs, uint, 0444); -#define MAX_QUEUES_DEFAULT 8 unsigned int xenvif_max_queues; module_param_named(max_queues, xenvif_max_queues, uint, 0644); MODULE_PARM_DESC(max_queues, @@ -688,7 +687,6 @@ static void tx_add_credit(struct xenvif_queue *queue) max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */ queue->remaining_credit = min(max_credit, max_burst); - queue->rate_limited = false; } void xenvif_tx_credit_callback(unsigned long data) @@ -1186,10 +1184,8 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size) msecs_to_jiffies(queue->credit_usec / 1000); /* Timer could already be pending in rare cases. */ - if (timer_pending(&queue->credit_timeout)) { - queue->rate_limited = true; + if (timer_pending(&queue->credit_timeout)) return true; - } /* Passed the point where we can replenish credit? */ if (time_after_eq64(now, next_credit)) { @@ -1204,7 +1200,6 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size) mod_timer(&queue->credit_timeout, next_credit); queue->credit_window_start = next_credit; - queue->rate_limited = true; return true; } @@ -2158,12 +2153,11 @@ static int __init netback_init(void) if (!xen_domain()) return -ENODEV; - /* Allow as many queues as there are CPUs but max. 8 if user has not + /* Allow as many queues as there are CPUs if user has not * specified a value. */ if (xenvif_max_queues == 0) - xenvif_max_queues = min_t(unsigned int, MAX_QUEUES_DEFAULT, - num_online_cpus()); + xenvif_max_queues = num_online_cpus(); if (fatal_skb_slots < XEN_NETBK_LEGACY_SLOTS_MAX) { pr_info("fatal_skb_slots too small (%d), bump it to XEN_NETBK_LEGACY_SLOTS_MAX (%d)\n", diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 68d0a5c9d437..d6abf191122a 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -86,9 +86,6 @@ struct netfront_cb { /* IRQ name is queue name with "-tx" or "-rx" appended */ #define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3) -static DECLARE_WAIT_QUEUE_HEAD(module_load_q); -static DECLARE_WAIT_QUEUE_HEAD(module_unload_q); - struct netfront_stats { u64 packets; u64 bytes; @@ -239,7 +236,7 @@ static void rx_refill_timeout(unsigned long data) static int netfront_tx_slot_available(struct netfront_queue *queue) { return (queue->tx.req_prod_pvt - queue->tx.rsp_cons) < - (NET_TX_RING_SIZE - XEN_NETIF_NR_SLOTS_MIN - 1); + (NET_TX_RING_SIZE - MAX_SKB_FRAGS - 2); } static void xennet_maybe_wake_tx(struct netfront_queue *queue) @@ -307,7 +304,7 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue) queue->rx_skbs[id] = skb; ref = gnttab_claim_grant_reference(&queue->gref_rx_head); - WARN_ON_ONCE(IS_ERR_VALUE((unsigned long)(int)ref)); + BUG_ON((signed short)ref < 0); queue->grant_rx_ref[id] = ref; page = skb_frag_page(&skb_shinfo(skb)->frags[0]); @@ -324,7 +321,7 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue) queue->rx.req_prod_pvt = req_prod; /* Not enough requests? Try again later. */ - if (req_prod - queue->rx.sring->req_prod < NET_RX_SLOTS_MIN) { + if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN) { mod_timer(&queue->rx_refill_timer, jiffies + (HZ/10)); return; } @@ -343,9 +340,6 @@ static int xennet_open(struct net_device *dev) unsigned int i = 0; struct netfront_queue *queue = NULL; - if (!np->queues) - return -ENODEV; - for (i = 0; i < num_queues; ++i) { queue = &np->queues[i]; napi_enable(&queue->napi); @@ -443,7 +437,7 @@ static void xennet_tx_setup_grant(unsigned long gfn, unsigned int offset, id = get_id_from_freelist(&queue->tx_skb_freelist, queue->tx_skbs); tx = RING_GET_REQUEST(&queue->tx, queue->tx.req_prod_pvt++); ref = gnttab_claim_grant_reference(&queue->gref_tx_head); - WARN_ON_ONCE(IS_ERR_VALUE((unsigned long)(int)ref)); + BUG_ON((signed short)ref < 0); gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id, gfn, GNTMAP_readonly); @@ -776,7 +770,7 @@ static int xennet_get_responses(struct netfront_queue *queue, RING_IDX cons = queue->rx.rsp_cons; struct sk_buff *skb = xennet_get_rx_skb(queue, cons); grant_ref_t ref = xennet_get_rx_ref(queue, cons); - int max = XEN_NETIF_NR_SLOTS_MIN + (rx->status <= RX_COPY_THRESHOLD); + int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD); int slots = 1; int err = 0; unsigned long ret; @@ -879,6 +873,7 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue, struct sk_buff *skb, struct sk_buff_head *list) { + struct skb_shared_info *shinfo = skb_shinfo(skb); RING_IDX cons = queue->rx.rsp_cons; struct sk_buff *nskb; @@ -887,16 +882,15 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue, RING_GET_RESPONSE(&queue->rx, ++cons); skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0]; - if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS) { + if (shinfo->nr_frags == MAX_SKB_FRAGS) { unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to; BUG_ON(pull_to <= skb_headlen(skb)); __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); } - BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS); + BUG_ON(shinfo->nr_frags >= MAX_SKB_FRAGS); - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, - skb_frag_page(nfrag), + skb_add_rx_frag(skb, shinfo->nr_frags, skb_frag_page(nfrag), rx->offset, rx->status, PAGE_SIZE); skb_shinfo(nskb)->nr_frags = 0; @@ -1335,12 +1329,6 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev) netif_carrier_off(netdev); - xenbus_switch_state(dev, XenbusStateInitialising); - wait_event(module_load_q, - xenbus_read_driver_state(dev->otherend) != - XenbusStateClosed && - xenbus_read_driver_state(dev->otherend) != - XenbusStateUnknown); return netdev; exit: @@ -1372,8 +1360,18 @@ static int netfront_probe(struct xenbus_device *dev, #ifdef CONFIG_SYSFS info->netdev->sysfs_groups[0] = &xennet_dev_group; #endif + err = register_netdev(info->netdev); + if (err) { + pr_warn("%s: register_netdev err=%d\n", __func__, err); + goto fail; + } return 0; + + fail: + xennet_free_netdev(netdev); + dev_set_drvdata(&dev->dev, NULL); + return err; } static void xennet_end_access(int ref, void *page) @@ -1393,8 +1391,6 @@ static void xennet_disconnect_backend(struct netfront_info *info) for (i = 0; i < num_queues && info->queues; ++i) { struct netfront_queue *queue = &info->queues[i]; - del_timer_sync(&queue->rx_refill_timer); - if (queue->tx_irq && (queue->tx_irq == queue->rx_irq)) unbind_from_irqhandler(queue->tx_irq, queue); if (queue->tx_irq && (queue->tx_irq != queue->rx_irq)) { @@ -1742,14 +1738,19 @@ static void xennet_destroy_queues(struct netfront_info *info) { unsigned int i; + rtnl_lock(); + for (i = 0; i < info->netdev->real_num_tx_queues; i++) { struct netfront_queue *queue = &info->queues[i]; if (netif_running(info->netdev)) napi_disable(&queue->napi); + del_timer_sync(&queue->rx_refill_timer); netif_napi_del(&queue->napi); } + rtnl_unlock(); + kfree(info->queues); info->queues = NULL; } @@ -1765,6 +1766,8 @@ static int xennet_create_queues(struct netfront_info *info, if (!info->queues) return -ENOMEM; + rtnl_lock(); + for (i = 0; i < *num_queues; i++) { struct netfront_queue *queue = &info->queues[i]; @@ -1773,7 +1776,7 @@ static int xennet_create_queues(struct netfront_info *info, ret = xennet_init_queue(queue); if (ret < 0) { - dev_warn(&info->xbdev->dev, + dev_warn(&info->netdev->dev, "only created %d queues\n", i); *num_queues = i; break; @@ -1787,8 +1790,10 @@ static int xennet_create_queues(struct netfront_info *info, netif_set_real_num_tx_queues(info->netdev, *num_queues); + rtnl_unlock(); + if (*num_queues == 0) { - dev_err(&info->xbdev->dev, "no queues\n"); + dev_err(&info->netdev->dev, "no queues\n"); return -EINVAL; } return 0; @@ -1830,25 +1835,31 @@ static int talk_to_netback(struct xenbus_device *dev, goto out; } - rtnl_lock(); if (info->queues) xennet_destroy_queues(info); err = xennet_create_queues(info, &num_queues); - if (err < 0) { - xenbus_dev_fatal(dev, err, "creating queues"); - kfree(info->queues); - info->queues = NULL; - goto out; - } - rtnl_unlock(); + if (err < 0) + goto destroy_ring; /* Create shared ring, alloc event channel -- for each queue */ for (i = 0; i < num_queues; ++i) { queue = &info->queues[i]; err = setup_netfront(dev, queue, feature_split_evtchn); - if (err) - goto destroy_ring; + if (err) { + /* setup_netfront() will tidy up the current + * queue on error, but we need to clean up + * those already allocated. + */ + if (i > 0) { + rtnl_lock(); + netif_set_real_num_tx_queues(info->netdev, i); + rtnl_unlock(); + goto destroy_ring; + } else { + goto out; + } + } } again: @@ -1938,11 +1949,9 @@ static int talk_to_netback(struct xenbus_device *dev, xenbus_transaction_end(xbt, 1); destroy_ring: xennet_disconnect_backend(info); - rtnl_lock(); - xennet_destroy_queues(info); + kfree(info->queues); + info->queues = NULL; out: - rtnl_unlock(); - device_unregister(&dev->dev); return err; } @@ -1977,15 +1986,6 @@ static int xennet_connect(struct net_device *dev) netdev_update_features(dev); rtnl_unlock(); - if (dev->reg_state == NETREG_UNINITIALIZED) { - err = register_netdev(dev); - if (err) { - pr_warn("%s: register_netdev err=%d\n", __func__, err); - device_unregister(&np->xbdev->dev); - return err; - } - } - /* * All public and private state should now be sane. Get * ready to start sending and receiving packets and give the driver @@ -2028,10 +2028,7 @@ static void netback_changed(struct xenbus_device *dev, case XenbusStateInitialised: case XenbusStateReconfiguring: case XenbusStateReconfigured: - break; - case XenbusStateUnknown: - wake_up_all(&module_unload_q); break; case XenbusStateInitWait: @@ -2047,12 +2044,10 @@ static void netback_changed(struct xenbus_device *dev, break; case XenbusStateClosed: - wake_up_all(&module_unload_q); if (dev->state == XenbusStateClosed) break; /* Missed the backend's CLOSING state -- fallthrough */ case XenbusStateClosing: - wake_up_all(&module_unload_q); xenbus_frontend_closed(dev); break; } @@ -2158,32 +2153,12 @@ static int xennet_remove(struct xenbus_device *dev) dev_dbg(&dev->dev, "%s\n", dev->nodename); - if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) { - xenbus_switch_state(dev, XenbusStateClosing); - wait_event(module_unload_q, - xenbus_read_driver_state(dev->otherend) == - XenbusStateClosing || - xenbus_read_driver_state(dev->otherend) == - XenbusStateUnknown); - - xenbus_switch_state(dev, XenbusStateClosed); - wait_event(module_unload_q, - xenbus_read_driver_state(dev->otherend) == - XenbusStateClosed || - xenbus_read_driver_state(dev->otherend) == - XenbusStateUnknown); - } - xennet_disconnect_backend(info); - if (info->netdev->reg_state == NETREG_REGISTERED) - unregister_netdev(info->netdev); + unregister_netdev(info->netdev); - if (info->queues) { - rtnl_lock(); + if (info->queues) xennet_destroy_queues(info); - rtnl_unlock(); - } xennet_free_netdev(info->netdev); return 0; diff --git a/include/linux/filter.h b/include/linux/filter.h index 677fa3b42194..5110d4211866 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -421,11 +421,7 @@ static inline void bpf_prog_unlock_ro(struct bpf_prog *fp) } #endif /* CONFIG_DEBUG_SET_MODULE_RONX */ -int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap); -static inline int sk_filter(struct sock *sk, struct sk_buff *skb) -{ - return sk_filter_trim_cap(sk, skb, 1); -} +int sk_filter(struct sock *sk, struct sk_buff *skb); int bpf_prog_select_runtime(struct bpf_prog *fp); void bpf_prog_free(struct bpf_prog *fp); @@ -466,9 +462,6 @@ u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); void bpf_int_jit_compile(struct bpf_prog *fp); bool bpf_helper_changes_skb_data(void *func); -struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off, - const struct bpf_insn *patch, u32 len); - #ifdef CONFIG_BPF_JIT typedef void (*bpf_jit_fill_hole_t)(void *area, unsigned int size); diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index dd676ba758ee..67ce5bd3b56a 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -585,7 +585,7 @@ static inline bool skb_vlan_tagged(const struct sk_buff *skb) * Returns true if the skb is tagged with multiple vlan headers, regardless * of whether it is hardware accelerated or not. */ -static inline bool skb_vlan_tagged_multi(struct sk_buff *skb) +static inline bool skb_vlan_tagged_multi(const struct sk_buff *skb) { __be16 protocol = skb->protocol; @@ -596,9 +596,6 @@ static inline bool skb_vlan_tagged_multi(struct sk_buff *skb) protocol != htons(ETH_P_8021AD))) return false; - if (unlikely(!pskb_may_pull(skb, VLAN_ETH_HLEN))) - return false; - veh = (struct vlan_ethhdr *)skb->data; protocol = veh->h_vlan_encapsulated_proto; } @@ -616,19 +613,18 @@ static inline bool skb_vlan_tagged_multi(struct sk_buff *skb) * * Returns features without unsafe ones if the skb has multiple tags. */ -static inline netdev_features_t vlan_features_check(struct sk_buff *skb, +static inline netdev_features_t vlan_features_check(const struct sk_buff *skb, netdev_features_t features) { - if (skb_vlan_tagged_multi(skb)) { - /* In the case of multi-tagged packets, use a direct mask - * instead of using netdev_interesect_features(), to make - * sure that only devices supporting NETIF_F_HW_CSUM will - * have checksum offloading support. - */ - features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | - NETIF_F_FRAGLIST | NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_STAG_TX; - } + if (skb_vlan_tagged_multi(skb)) + features = netdev_intersect_features(features, + NETIF_F_SG | + NETIF_F_HIGHDMA | + NETIF_F_FRAGLIST | + NETIF_F_GEN_CSUM | + NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX); + return features; } diff --git a/include/linux/mroute.h b/include/linux/mroute.h index d5277fc3ce2e..79aaa9fc1a15 100644 --- a/include/linux/mroute.h +++ b/include/linux/mroute.h @@ -103,5 +103,5 @@ struct mfc_cache { struct rtmsg; extern int ipmr_get_route(struct net *net, struct sk_buff *skb, __be32 saddr, __be32 daddr, - struct rtmsg *rtm, int nowait, u32 portid); + struct rtmsg *rtm, int nowait); #endif diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index fc54049e8286..424562b28895 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -511,6 +511,7 @@ static inline void napi_enable(struct napi_struct *n) clear_bit(NAPI_STATE_NPSVC, &n->state); } +#ifdef CONFIG_SMP /** * napi_synchronize - wait until NAPI is not running * @n: napi context @@ -521,12 +522,12 @@ static inline void napi_enable(struct napi_struct *n) */ static inline void napi_synchronize(const struct napi_struct *n) { - if (IS_ENABLED(CONFIG_SMP)) - while (test_bit(NAPI_STATE_SCHED, &n->state)) - msleep(1); - else - barrier(); + while (test_bit(NAPI_STATE_SCHED, &n->state)) + msleep(1); } +#else +# define napi_synchronize(n) barrier() +#endif enum netdev_queue_state_t { __QUEUE_STATE_DRV_XOFF, @@ -1399,7 +1400,6 @@ enum netdev_priv_flags { * @mtu: Interface MTU value * @type: Interface hardware type * @hard_header_len: Maximum hardware header length. - * @min_header_len: Minimum hardware header length * * @needed_headroom: Extra headroom the hardware may need, but not in all * cases can this be guaranteed @@ -1620,7 +1620,6 @@ struct net_device { unsigned int mtu; unsigned short type; unsigned short hard_header_len; - unsigned short min_header_len; unsigned short needed_headroom; unsigned short needed_tailroom; @@ -2005,10 +2004,7 @@ struct napi_gro_cb { /* Used in foo-over-udp, set in udp[46]_gro_receive */ u8 is_ipv6:1; - /* Number of gro_receive callbacks this packet already went through */ - u8 recursion_counter:4; - - /* 3 bit hole */ + /* 7 bit hole */ /* used to support CHECKSUM_COMPLETE for tunneling protocols */ __wsum csum; @@ -2019,25 +2015,6 @@ struct napi_gro_cb { #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb) -#define GRO_RECURSION_LIMIT 15 -static inline int gro_recursion_inc_test(struct sk_buff *skb) -{ - return ++NAPI_GRO_CB(skb)->recursion_counter == GRO_RECURSION_LIMIT; -} - -typedef struct sk_buff **(*gro_receive_t)(struct sk_buff **, struct sk_buff *); -static inline struct sk_buff **call_gro_receive(gro_receive_t cb, - struct sk_buff **head, - struct sk_buff *skb) -{ - if (unlikely(gro_recursion_inc_test(skb))) { - NAPI_GRO_CB(skb)->flush |= 1; - return NULL; - } - - return cb(head, skb); -} - struct packet_type { __be16 type; /* This is really htons(ether_type). */ struct net_device *dev; /* NULL is wildcarded here */ @@ -2083,22 +2060,6 @@ struct udp_offload { struct udp_offload_callbacks callbacks; }; -typedef struct sk_buff **(*gro_receive_udp_t)(struct sk_buff **, - struct sk_buff *, - struct udp_offload *); -static inline struct sk_buff **call_gro_receive_udp(gro_receive_udp_t cb, - struct sk_buff **head, - struct sk_buff *skb, - struct udp_offload *uoff) -{ - if (unlikely(gro_recursion_inc_test(skb))) { - NAPI_GRO_CB(skb)->flush |= 1; - return NULL; - } - - return cb(head, skb, uoff); -} - /* often modified stats are per cpu, other are shared (netdev->stats) */ struct pcpu_sw_netstats { u64 rx_packets; @@ -2327,19 +2288,14 @@ static inline int skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen) return NAPI_GRO_CB(skb)->frag0_len < hlen; } -static inline void skb_gro_frag0_invalidate(struct sk_buff *skb) -{ - NAPI_GRO_CB(skb)->frag0 = NULL; - NAPI_GRO_CB(skb)->frag0_len = 0; -} - static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen, unsigned int offset) { if (!pskb_may_pull(skb, hlen)) return NULL; - skb_gro_frag0_invalidate(skb); + NAPI_GRO_CB(skb)->frag0 = NULL; + NAPI_GRO_CB(skb)->frag0_len = 0; return skb->data + offset; } @@ -2543,8 +2499,6 @@ static inline bool dev_validate_header(const struct net_device *dev, { if (likely(len >= dev->hard_header_len)) return true; - if (len < dev->min_header_len) - return false; if (capable(CAP_SYS_RAWIO)) { memset(ll_header + len, 0, dev->hard_header_len - len); @@ -3083,7 +3037,6 @@ static inline void napi_free_frags(struct napi_struct *napi) napi->skb = NULL; } -bool netdev_is_rx_handler_busy(struct net_device *dev); int netdev_rx_handler_register(struct net_device *dev, rx_handler_func_t *rx_handler, void *rx_handler_data); @@ -3469,9 +3422,6 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, unsigned char name_assign_type, void (*setup)(struct net_device *), unsigned int txqs, unsigned int rxqs); -int dev_get_valid_name(struct net *net, struct net_device *dev, - const char *name); - #define alloc_netdev(sizeof_priv, name, name_assign_type, setup) \ alloc_netdev_mqs(sizeof_priv, name, name_assign_type, setup, 1, 1) diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h index 8793f5a7b820..1d6a935c1ac5 100644 --- a/include/linux/netfilter/ipset/ip_set_timeout.h +++ b/include/linux/netfilter/ipset/ip_set_timeout.h @@ -65,14 +65,8 @@ ip_set_timeout_set(unsigned long *timeout, u32 value) static inline u32 ip_set_timeout_get(unsigned long *timeout) { - u32 t; - - if (*timeout == IPSET_ELEM_PERMANENT) - return 0; - - t = jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; - /* Zero value in userspace means no timeout */ - return t == 0 ? 1 : t; + return *timeout == IPSET_ELEM_PERMANENT ? 0 : + jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; } #endif /* __KERNEL__ */ diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 6923e4049de3..c5577410c25d 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -239,24 +239,11 @@ void xt_unregister_match(struct xt_match *target); int xt_register_matches(struct xt_match *match, unsigned int n); void xt_unregister_matches(struct xt_match *match, unsigned int n); -int xt_check_entry_offsets(const void *base, const char *elems, - unsigned int target_offset, - unsigned int next_offset); - -unsigned int *xt_alloc_entry_offsets(unsigned int size); -bool xt_find_jump_offset(const unsigned int *offsets, - unsigned int target, unsigned int size); - -int xt_check_proc_name(const char *name, unsigned int size); - int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto, bool inv_proto); int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto, bool inv_proto); -void *xt_copy_counters_from_user(const void __user *user, unsigned int len, - struct xt_counters_info *info, bool compat); - struct xt_table *xt_register_table(struct net *net, const struct xt_table *table, struct xt_table_info *bootstrap, @@ -370,14 +357,38 @@ static inline unsigned long ifname_compare_aligned(const char *_a, return ret; } -struct xt_percpu_counter_alloc_state { - unsigned int off; - const char __percpu *mem; -}; -bool xt_percpu_counter_alloc(struct xt_percpu_counter_alloc_state *state, - struct xt_counters *counter); -void xt_percpu_counter_free(struct xt_counters *cnt); +/* On SMP, ip(6)t_entry->counters.pcnt holds address of the + * real (percpu) counter. On !SMP, its just the packet count, + * so nothing needs to be done there. + * + * xt_percpu_counter_alloc returns the address of the percpu + * counter, or 0 on !SMP. We force an alignment of 16 bytes + * so that bytes/packets share a common cache line. + * + * Hence caller must use IS_ERR_VALUE to check for error, this + * allows us to return 0 for single core systems without forcing + * callers to deal with SMP vs. NONSMP issues. + */ +static inline u64 xt_percpu_counter_alloc(void) +{ + if (nr_cpu_ids > 1) { + void __percpu *res = __alloc_percpu(sizeof(struct xt_counters), + sizeof(struct xt_counters)); + + if (res == NULL) + return (u64) -ENOMEM; + + return (u64) (__force unsigned long) res; + } + + return 0; +} +static inline void xt_percpu_counter_free(u64 pcnt) +{ + if (nr_cpu_ids > 1) + free_percpu((void __percpu *) (unsigned long) pcnt); +} static inline struct xt_counters * xt_get_this_cpu_counter(struct xt_counters *cnt) @@ -467,7 +478,7 @@ void xt_compat_init_offsets(u_int8_t af, unsigned int number); int xt_compat_calc_jump(u_int8_t af, unsigned int offset); int xt_compat_match_offset(const struct xt_match *match); -void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, +int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, unsigned int *size); int xt_compat_match_to_user(const struct xt_entry_match *m, void __user **dstptr, unsigned int *size); @@ -477,9 +488,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, unsigned int *size); int xt_compat_target_to_user(const struct xt_entry_target *t, void __user **dstptr, unsigned int *size); -int xt_compat_check_entry_offsets(const void *base, const char *elems, - unsigned int target_offset, - unsigned int next_offset); #endif /* CONFIG_COMPAT */ #endif /* _X_TABLES_H */ diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index df50a40b5474..39c556c66c12 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -520,7 +520,6 @@ static inline bool skb_mstamp_after(const struct skb_mstamp *t1, * @hash: the packet hash * @queue_mapping: Queue mapping for multiqueue devices * @xmit_more: More SKBs are pending for this queue - * @pfmemalloc: skbuff was allocated from PFMEMALLOC reserves * @ndisc_nodetype: router type (from link layer) * @ooo_okay: allow the mapping of a socket to a queue to be changed * @l4_hash: indicate hash is a canonical 4-tuple hash over transport @@ -605,8 +604,8 @@ struct sk_buff { fclone:2, peeked:1, head_frag:1, - xmit_more:1, - pfmemalloc:1; + xmit_more:1; + /* one bit hole */ kmemcheck_bitfield_end(flags1); /* fields enclosed in headers_start/headers_end are copied @@ -626,18 +625,19 @@ struct sk_buff { __u8 __pkt_type_offset[0]; __u8 pkt_type:3; + __u8 pfmemalloc:1; __u8 ignore_df:1; __u8 nfctinfo:3; - __u8 nf_trace:1; + __u8 nf_trace:1; __u8 ip_summed:2; __u8 ooo_okay:1; __u8 l4_hash:1; __u8 sw_hash:1; __u8 wifi_acked_valid:1; __u8 wifi_acked:1; - __u8 no_fcs:1; + __u8 no_fcs:1; /* Indicates the inner headers are valid in the skbuff. */ __u8 encapsulation:1; __u8 encap_hdr_csum:1; @@ -645,11 +645,11 @@ struct sk_buff { __u8 csum_complete_sw:1; __u8 csum_level:2; __u8 csum_bad:1; + #ifdef CONFIG_IPV6_NDISC_NODETYPE __u8 ndisc_nodetype:2; #endif __u8 ipvs_property:1; - __u8 inner_protocol_type:1; __u8 remcsum_offload:1; /* 3 or 5 bit hole */ @@ -893,10 +893,10 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom); struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom, int newtailroom, gfp_t priority); -int __must_check skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg, - int offset, int len); -int __must_check skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, - int offset, int len); +int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg, + int offset, int len); +int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, + int len); int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer); int skb_pad(struct sk_buff *skb, int pad); #define dev_kfree_skb(a) consume_skb(a) @@ -996,7 +996,6 @@ __skb_set_sw_hash(struct sk_buff *skb, __u32 hash, bool is_l4) } void __skb_get_hash(struct sk_buff *skb); -u32 __skb_get_hash_symmetric(struct sk_buff *skb); u32 skb_get_poff(const struct sk_buff *skb); u32 __skb_get_poff(const struct sk_buff *skb, void *data, const struct flow_keys *keys, int hlen); @@ -1098,6 +1097,9 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from) static inline void skb_sender_cpu_clear(struct sk_buff *skb) { +#ifdef CONFIG_XPS + skb->sender_cpu = 0; +#endif } #ifdef NET_SKBUFF_DATA_USES_OFFSET @@ -2576,13 +2578,6 @@ static inline int skb_clone_writable(const struct sk_buff *skb, unsigned int len skb_headroom(skb) + len <= skb->hdr_len; } -static inline int skb_try_make_writable(struct sk_buff *skb, - unsigned int write_len) -{ - return skb_cloned(skb) && !skb_clone_writable(skb, write_len) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC); -} - static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom, int cloned) { @@ -2784,25 +2779,6 @@ static inline void skb_postpush_rcsum(struct sk_buff *skb, skb->csum = csum_partial(start, len, skb->csum); } -/** - * skb_push_rcsum - push skb and update receive checksum - * @skb: buffer to update - * @len: length of data pulled - * - * This function performs an skb_push on the packet and updates - * the CHECKSUM_COMPLETE checksum. It should be used on - * receive path processing instead of skb_push unless you know - * that the checksum difference is zero (e.g., a valid IP header) - * or you are setting ip_summed to CHECKSUM_NONE. - */ -static inline unsigned char *skb_push_rcsum(struct sk_buff *skb, - unsigned int len) -{ - skb_push(skb, len); - skb_postpush_rcsum(skb, skb->data, len); - return skb->data; -} - /** * pskb_trim_rcsum - trim received skb and update checksum * @skb: buffer to trim @@ -3414,13 +3390,6 @@ static inline void nf_reset_trace(struct sk_buff *skb) #endif } -static inline void ipvs_reset(struct sk_buff *skb) -{ -#if IS_ENABLED(CONFIG_IP_VS) - skb->ipvs_property = 0; -#endif -} - /* Note: This doesn't put any conntrack and bridge info in dst. */ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src, bool copy) diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 9cba4907695c..d540657819ef 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -20,8 +20,6 @@ #define ADDRCONF_TIMER_FUZZ (HZ / 4) #define ADDRCONF_TIMER_FUZZ_MAX (HZ) -#define ADDRCONF_NOTIFY_PRIORITY 0 - #include #include diff --git a/include/net/af_unix.h b/include/net/af_unix.h index fd60eccb59a6..9b4c418bebd8 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -52,7 +52,7 @@ struct unix_sock { struct sock sk; struct unix_address *addr; struct path path; - struct mutex iolock, bindlock; + struct mutex readlock; struct sock *peer; struct list_head link; atomic_long_t inflight; diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h index f7a35fcaaaf6..e9eb2d6791b3 100644 --- a/include/net/af_vsock.h +++ b/include/net/af_vsock.h @@ -62,8 +62,7 @@ struct vsock_sock { struct list_head pending_links; struct list_head accept_queue; bool rejected; - struct delayed_work connect_work; - struct delayed_work pending_work; + struct delayed_work dwork; u32 peer_shutdown; bool sent_request; bool ignore_connecting_rst; @@ -74,6 +73,7 @@ struct vsock_sock { s64 vsock_stream_has_data(struct vsock_sock *vsk); s64 vsock_stream_has_space(struct vsock_sock *vsk); +void vsock_pending_work(struct work_struct *work); struct sock *__vsock_create(struct net *net, struct socket *sock, struct sock *parent, diff --git a/include/net/arp.h b/include/net/arp.h index 1b3f86981757..5e0f891d476c 100644 --- a/include/net/arp.h +++ b/include/net/arp.h @@ -19,9 +19,6 @@ static inline u32 arp_hashfn(const void *pkey, const struct net_device *dev, u32 static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key) { - if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) - key = INADDR_ANY; - return ___neigh_lookup_noref(&arp_tbl, neigh_key_eq32, arp_hashfn, &key, dev); } diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 876688b5a356..1878d0a96333 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -878,7 +878,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst, u16 conn_timeout, u8 role); struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u16 conn_timeout, - u8 role, bdaddr_t *direct_rpa); + u8 role); struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, u8 sec_level, u8 auth_type); struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index c05748cc1b20..2c7bdb81d30c 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -933,9 +933,9 @@ enum rate_info_flags { * @RATE_INFO_BW_160: 160 MHz bandwidth */ enum rate_info_bw { - RATE_INFO_BW_20 = 0, RATE_INFO_BW_5, RATE_INFO_BW_10, + RATE_INFO_BW_20, RATE_INFO_BW_40, RATE_INFO_BW_80, RATE_INFO_BW_160, @@ -4257,17 +4257,6 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, */ void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss); -/** - * cfg80211_abandon_assoc - notify cfg80211 of abandoned association attempt - * @dev: network device - * @bss: The BSS entry with which association was abandoned. - * - * Call this whenever - for reasons reported through other API, like deauth RX, - * an association attempt was abandoned. - * This function may sleep. The caller must hold the corresponding wdev's mutex. - */ -void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss); - /** * cfg80211_tx_mlme_mgmt - notification of transmitted deauth/disassoc frame * @dev: network device diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index a34b141f125f..3ebb168b9afc 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h @@ -309,10 +309,6 @@ static inline int cipso_v4_validate(const struct sk_buff *skb, } for (opt_iter = 6; opt_iter < opt_len;) { - if (opt_iter + 1 == opt_len) { - err_offset = opt_iter; - goto out; - } tag_len = opt[opt_iter + 1]; if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) { err_offset = opt_iter + 1; diff --git a/include/net/dst.h b/include/net/dst.h index e4f450617919..c7329dcd90cc 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -110,16 +110,10 @@ struct dst_entry { }; }; -struct dst_metrics { - u32 metrics[RTAX_MAX]; - atomic_t refcnt; -}; -extern const struct dst_metrics dst_default_metrics; - u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); +extern const u32 dst_default_metrics[]; #define DST_METRICS_READ_ONLY 0x1UL -#define DST_METRICS_REFCOUNTED 0x2UL #define DST_METRICS_FLAGS 0x3UL #define __DST_METRICS_PTR(Y) \ ((u32 *)((Y) & ~DST_METRICS_FLAGS)) diff --git a/include/net/dst_cache.h b/include/net/dst_cache.h deleted file mode 100644 index 151accae708b..000000000000 --- a/include/net/dst_cache.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef _NET_DST_CACHE_H -#define _NET_DST_CACHE_H - -#include -#include -#if IS_ENABLED(CONFIG_IPV6) -#include -#endif - -struct dst_cache { - struct dst_cache_pcpu __percpu *cache; - unsigned long reset_ts; -}; - -/** - * dst_cache_get - perform cache lookup - * @dst_cache: the cache - * - * The caller should use dst_cache_get_ip4() if it need to retrieve the - * source address to be used when xmitting to the cached dst. - * local BH must be disabled. - */ -struct dst_entry *dst_cache_get(struct dst_cache *dst_cache); - -/** - * dst_cache_get_ip4 - perform cache lookup and fetch ipv4 source address - * @dst_cache: the cache - * @saddr: return value for the retrieved source address - * - * local BH must be disabled. - */ -struct rtable *dst_cache_get_ip4(struct dst_cache *dst_cache, __be32 *saddr); - -/** - * dst_cache_set_ip4 - store the ipv4 dst into the cache - * @dst_cache: the cache - * @dst: the entry to be cached - * @saddr: the source address to be stored inside the cache - * - * local BH must be disabled. - */ -void dst_cache_set_ip4(struct dst_cache *dst_cache, struct dst_entry *dst, - __be32 saddr); - -#if IS_ENABLED(CONFIG_IPV6) - -/** - * dst_cache_set_ip6 - store the ipv6 dst into the cache - * @dst_cache: the cache - * @dst: the entry to be cached - * @saddr: the source address to be stored inside the cache - * - * local BH must be disabled. - */ -void dst_cache_set_ip6(struct dst_cache *dst_cache, struct dst_entry *dst, - const struct in6_addr *addr); - -/** - * dst_cache_get_ip6 - perform cache lookup and fetch ipv6 source address - * @dst_cache: the cache - * @saddr: return value for the retrieved source address - * - * local BH must be disabled. - */ -struct dst_entry *dst_cache_get_ip6(struct dst_cache *dst_cache, - struct in6_addr *saddr); -#endif - -/** - * dst_cache_reset - invalidate the cache contents - * @dst_cache: the cache - * - * This do not free the cached dst to avoid races and contentions. - * the dst will be freed on later cache lookup. - */ -static inline void dst_cache_reset(struct dst_cache *dst_cache) -{ - dst_cache->reset_ts = jiffies; -} - -/** - * dst_cache_init - initialize the cache, allocating the required storage - * @dst_cache: the cache - * @gfp: allocation flags - */ -int dst_cache_init(struct dst_cache *dst_cache, gfp_t gfp); - -/** - * dst_cache_destroy - empty the cache and free the allocated storage - * @dst_cache: the cache - * - * No synchronization is enforced: it must be called only when the cache - * is unsed. - */ -void dst_cache_destroy(struct dst_cache *dst_cache); - -#endif diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 43c0e771f417..1b6b6dcb018d 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -114,7 +114,6 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net) * @flags: flags * @policy: attribute validation policy * @doit: standard command callback - * @start: start callback for dumps * @dumpit: callback for dumpers * @done: completion callback for dumps * @ops_list: operations list @@ -123,7 +122,6 @@ struct genl_ops { const struct nla_policy *policy; int (*doit)(struct sk_buff *skb, struct genl_info *info); - int (*start)(struct netlink_callback *cb); int (*dumpit)(struct sk_buff *skb, struct netlink_callback *cb); int (*done)(struct netlink_callback *cb); diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h index c26a6e4dc306..ac42bbb37b2d 100644 --- a/include/net/inet_frag.h +++ b/include/net/inet_frag.h @@ -1,9 +1,14 @@ #ifndef __NET_FRAG_H__ #define __NET_FRAG_H__ +#include + struct netns_frags { - /* Keep atomic mem on separate cachelines in structs that include it */ - atomic_t mem ____cacheline_aligned_in_smp; + /* The percpu_counter "mem" need to be cacheline aligned. + * mem.count must not share cacheline with other writers + */ + struct percpu_counter mem ____cacheline_aligned_in_smp; + /* sysctls */ int timeout; int high_thresh; @@ -103,10 +108,15 @@ struct inet_frags { int inet_frags_init(struct inet_frags *); void inet_frags_fini(struct inet_frags *); -static inline void inet_frags_init_net(struct netns_frags *nf) +static inline int inet_frags_init_net(struct netns_frags *nf) +{ + return percpu_counter_init(&nf->mem, 0, GFP_KERNEL); +} +static inline void inet_frags_uninit_net(struct netns_frags *nf) { - atomic_set(&nf->mem, 0); + percpu_counter_destroy(&nf->mem); } + void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f); void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); @@ -130,24 +140,37 @@ static inline bool inet_frag_evicting(struct inet_frag_queue *q) /* Memory Tracking Functions. */ +/* The default percpu_counter batch size is not big enough to scale to + * fragmentation mem acct sizes. + * The mem size of a 64K fragment is approx: + * (44 fragments * 2944 truesize) + frag_queue struct(200) = 129736 bytes + */ +static unsigned int frag_percpu_counter_batch = 130000; + static inline int frag_mem_limit(struct netns_frags *nf) { - return atomic_read(&nf->mem); + return percpu_counter_read(&nf->mem); } static inline void sub_frag_mem_limit(struct netns_frags *nf, int i) { - atomic_sub(i, &nf->mem); + __percpu_counter_add(&nf->mem, -i, frag_percpu_counter_batch); } static inline void add_frag_mem_limit(struct netns_frags *nf, int i) { - atomic_add(i, &nf->mem); + __percpu_counter_add(&nf->mem, i, frag_percpu_counter_batch); } -static inline int sum_frag_mem_limit(struct netns_frags *nf) +static inline unsigned int sum_frag_mem_limit(struct netns_frags *nf) { - return atomic_read(&nf->mem); + unsigned int res; + + local_bh_disable(); + res = percpu_counter_sum_positive(&nf->mem); + local_bh_enable(); + + return res; } /* RFC 3168 support : diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 8f16dedd75bb..23b8419e44b2 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -101,7 +101,7 @@ struct inet_request_sock { kmemcheck_bitfield_end(flags); u32 ir_mark; union { - struct ip_options_rcu __rcu *ireq_opt; + struct ip_options_rcu *opt; struct sk_buff *pktopts; }; }; @@ -119,12 +119,6 @@ static inline u32 inet_request_mark(const struct sock *sk, struct sk_buff *skb) return sk->sk_mark; } -static inline struct ip_options_rcu *ireq_opt_deref(const struct inet_request_sock *ireq) -{ - return rcu_dereference_check(ireq->ireq_opt, - atomic_read(&ireq->req.rsk_refcnt) > 0); -} - struct inet_cork { unsigned int flags; __be32 addr; diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index 567017b5fc9e..c9b3eb70f340 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -55,7 +55,6 @@ struct inet_timewait_sock { #define tw_family __tw_common.skc_family #define tw_state __tw_common.skc_state #define tw_reuse __tw_common.skc_reuse -#define tw_reuseport __tw_common.skc_reuseport #define tw_ipv6only __tw_common.skc_ipv6only #define tw_bound_dev_if __tw_common.skc_bound_dev_if #define tw_node __tw_common.skc_nulls_node diff --git a/include/net/ip.h b/include/net/ip.h index 10664a684acf..4f3ef345f4c2 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -33,8 +33,6 @@ #include #include -#define IPV4_MIN_MTU 68 /* RFC 791 */ - struct sock; struct inet_skb_parm { @@ -280,13 +278,6 @@ int ip_decrease_ttl(struct iphdr *iph) return --iph->ttl; } -static inline int ip_mtu_locked(const struct dst_entry *dst) -{ - const struct rtable *rt = (const struct rtable *)dst; - - return rt->rt_mtu_locked || dst_metric_locked(dst, RTAX_MTU); -} - static inline int ip_dont_fragment(const struct sock *sk, const struct dst_entry *dst) { @@ -294,7 +285,7 @@ int ip_dont_fragment(const struct sock *sk, const struct dst_entry *dst) return pmtudisc == IP_PMTUDISC_DO || (pmtudisc == IP_PMTUDISC_WANT && - !ip_mtu_locked(dst)); + !(dst_metric_locked(dst, RTAX_MTU))); } static inline bool ip_sk_accept_pmtu(const struct sock *sk) @@ -320,11 +311,11 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, struct net *net = dev_net(dst->dev); if (net->ipv4.sysctl_ip_fwd_use_pmtu || - ip_mtu_locked(dst) || + dst_metric_locked(dst, RTAX_MTU) || !forwarding) return dst_mtu(dst); - return min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU); + return min(dst->dev->mtu, IP_MAX_MTU); } static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb) @@ -337,7 +328,7 @@ static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb) return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding); } - return min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU); + return min(skb_dst(skb)->dev->mtu, IP_MAX_MTU); } u32 ip_idents_reserve(u32 hash, int segs); @@ -563,7 +554,7 @@ int ip_options_rcv_srr(struct sk_buff *skb); */ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb); -void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, int tlen, int offset); +void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, int offset); int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc, bool allow_ipv6); int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, @@ -585,7 +576,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport, static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) { - ip_cmsg_recv_offset(msg, skb, 0, 0); + ip_cmsg_recv_offset(msg, skb, 0); } bool icmp_global_allow(void); diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index fa5e703a14ed..fb961a576abe 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -68,7 +68,6 @@ struct fib6_node { __u16 fn_flags; int fn_sernum; struct rt6_info *rr_ptr; - struct rcu_head rcu; }; #ifndef CONFIG_IPV6_SUBTREES @@ -103,7 +102,7 @@ struct rt6_info { * the same cache line. */ struct fib6_table *rt6i_table; - struct fib6_node __rcu *rt6i_node; + struct fib6_node *rt6i_node; struct in6_addr rt6i_gateway; @@ -166,40 +165,13 @@ static inline void rt6_update_expires(struct rt6_info *rt0, int timeout) rt0->rt6i_flags |= RTF_EXPIRES; } -/* Function to safely get fn->sernum for passed in rt - * and store result in passed in cookie. - * Return true if we can get cookie safely - * Return false if not - */ -static inline bool rt6_get_cookie_safe(const struct rt6_info *rt, - u32 *cookie) -{ - struct fib6_node *fn; - bool status = false; - - rcu_read_lock(); - fn = rcu_dereference(rt->rt6i_node); - - if (fn) { - *cookie = fn->fn_sernum; - status = true; - } - - rcu_read_unlock(); - return status; -} - static inline u32 rt6_get_cookie(const struct rt6_info *rt) { - u32 cookie = 0; - if (rt->rt6i_flags & RTF_PCPU || (unlikely(rt->dst.flags & DST_NOCACHE) && rt->dst.from)) rt = (struct rt6_info *)(rt->dst.from); - rt6_get_cookie_safe(rt, &cookie); - - return cookie; + return rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; } static inline void ip6_rt_put(struct rt6_info *rt) diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index f9bdfb096579..af0e8c081191 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -21,7 +21,6 @@ struct route_info { #include #include #include -#include #include #include #include @@ -78,7 +77,6 @@ static inline struct dst_entry *ip6_route_output(struct net *net, struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6, int flags); -void ip6_route_init_special_entries(void); int ip6_route_init(void); void ip6_route_cleanup(void); @@ -210,11 +208,4 @@ static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, return daddr; } -static inline bool rt6_duplicate_nexthop(struct rt6_info *a, struct rt6_info *b) -{ - return a->dst.dev == b->dst.dev && - a->rt6i_idev == b->rt6i_idev && - ipv6_addr_equal(&a->rt6i_gateway, &b->rt6i_gateway) && - !lwtunnel_cmp_encap(a->dst.lwtstate, b->dst.lwtstate); -} #endif diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h index d143c8480681..ff788b665277 100644 --- a/include/net/ip6_tunnel.h +++ b/include/net/ip6_tunnel.h @@ -5,8 +5,6 @@ #include #include #include -#include -#include #define IP6TUNNEL_ERR_TIMEO (30*HZ) @@ -34,6 +32,12 @@ struct __ip6_tnl_parm { __be32 o_key; }; +struct ip6_tnl_dst { + seqlock_t lock; + struct dst_entry __rcu *dst; + u32 cookie; +}; + /* IPv6 tunnel */ struct ip6_tnl { struct ip6_tnl __rcu *next; /* next tunnel in list */ @@ -41,7 +45,7 @@ struct ip6_tnl { struct net *net; /* netns for packet i/o */ struct __ip6_tnl_parm parms; /* tunnel configuration parameters */ struct flowi fl; /* flowi template for xmit */ - struct dst_cache dst_cache; /* cached dst */ + struct ip6_tnl_dst __percpu *dst_cache; /* cached dst */ int err_count; unsigned long err_time; @@ -61,6 +65,11 @@ struct ipv6_tlv_tnl_enc_lim { __u8 encap_limit; /* tunnel encapsulation limit */ } __packed; +struct dst_entry *ip6_tnl_dst_get(struct ip6_tnl *t); +int ip6_tnl_dst_init(struct ip6_tnl *t); +void ip6_tnl_dst_destroy(struct ip6_tnl *t); +void ip6_tnl_dst_reset(struct ip6_tnl *t); +void ip6_tnl_dst_set(struct ip6_tnl *t, struct dst_entry *dst); int ip6_tnl_rcv_ctl(struct ip6_tnl *t, const struct in6_addr *laddr, const struct in6_addr *raddr); int ip6_tnl_xmit_ctl(struct ip6_tnl *t, const struct in6_addr *laddr, @@ -77,7 +86,6 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb, struct net_device_stats *stats = &dev->stats; int pkt_len, err; - memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); pkt_len = skb->len - skb_inner_network_offset(skb); err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb); diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 3afb7c4c7098..3f98233388fb 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -56,7 +56,6 @@ struct fib_nh_exception { int fnhe_genid; __be32 fnhe_daddr; u32 fnhe_pmtu; - bool fnhe_mtu_locked; __be32 fnhe_gw; unsigned long fnhe_expires; struct rtable __rcu *fnhe_rth_input; @@ -113,11 +112,11 @@ struct fib_info { unsigned char fib_type; __be32 fib_prefsrc; u32 fib_priority; - struct dst_metrics *fib_metrics; -#define fib_mtu fib_metrics->metrics[RTAX_MTU-1] -#define fib_window fib_metrics->metrics[RTAX_WINDOW-1] -#define fib_rtt fib_metrics->metrics[RTAX_RTT-1] -#define fib_advmss fib_metrics->metrics[RTAX_ADVMSS-1] + u32 *fib_metrics; +#define fib_mtu fib_metrics[RTAX_MTU-1] +#define fib_window fib_metrics[RTAX_WINDOW-1] +#define fib_rtt fib_metrics[RTAX_RTT-1] +#define fib_advmss fib_metrics[RTAX_ADVMSS-1] int fib_nhs; #ifdef CONFIG_IP_ROUTE_MULTIPATH int fib_weight; diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 74bc08d82e14..62a750a6a8f8 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -13,7 +13,6 @@ #include #include #include -#include #if IS_ENABLED(CONFIG_IPV6) #include @@ -86,6 +85,11 @@ struct ip_tunnel_prl_entry { struct rcu_head rcu_head; }; +struct ip_tunnel_dst { + struct dst_entry __rcu *dst; + __be32 saddr; +}; + struct metadata_dst; struct ip_tunnel { @@ -104,7 +108,7 @@ struct ip_tunnel { int tun_hlen; /* Precalculated header length */ int mlink; - struct dst_cache dst_cache; + struct ip_tunnel_dst __percpu *dst_cache; struct ip_tunnel_parm parms; @@ -226,7 +230,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd); int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t, u8 *protocol, struct flowi4 *fl4); -int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict); int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu); struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev, @@ -244,6 +247,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], struct ip_tunnel_parm *p); void ip_tunnel_setup(struct net_device *dev, int net_id); +void ip_tunnel_dst_reset_all(struct ip_tunnel *t); int ip_tunnel_encap_setup(struct ip_tunnel *t, struct ip_tunnel_encap *ipencap); @@ -278,22 +282,6 @@ struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md, struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum, int gso_type_mask); -static inline int iptunnel_pull_offloads(struct sk_buff *skb) -{ - if (skb_is_gso(skb)) { - int err; - - err = skb_unclone(skb, GFP_ATOMIC); - if (unlikely(err)) - return err; - skb_shinfo(skb)->gso_type &= ~(NETIF_F_GSO_ENCAP_ALL >> - NETIF_F_GSO_SHIFT); - } - - skb->encapsulation = 0; - return 0; -} - static inline void iptunnel_xmit_stats(int err, struct net_device_stats *err_stats, struct pcpu_sw_netstats __percpu *stats) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 0e01d570fa22..9a5c9f013784 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -281,7 +281,6 @@ int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq, int flags); int ip6_flowlabel_init(void); void ip6_flowlabel_cleanup(void); -bool ip6_autoflowlabel(struct net *net, const struct ipv6_pinfo *np); static inline void fl6_sock_release(struct ip6_flowlabel *fl) { @@ -745,11 +744,6 @@ static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb, { u32 hash; - /* @flowlabel may include more than a flow label, eg, the traffic class. - * Here we want only the flow label value. - */ - flowlabel &= IPV6_FLOWLABEL_MASK; - if (flowlabel || net->ipv6.sysctl.auto_flowlabels == IP6_AUTO_FLOW_LABEL_OFF || (!autolabel && @@ -762,7 +756,7 @@ static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb, * to minimize possbility that any useful information to an * attacker is leaked. Only lower 20 bits are relevant. */ - hash = rol32(hash, 16); + rol32(hash, 16); flowlabel = (__force __be32)hash & IPV6_FLOWLABEL_MASK; @@ -964,7 +958,6 @@ int inet6_hash_connect(struct inet_timewait_death_row *death_row, */ extern const struct proto_ops inet6_stream_ops; extern const struct proto_ops inet6_dgram_ops; -extern const struct proto_ops inet6_sockraw_ops; struct group_source_req; struct group_filter; diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index c2aa73e5e6bb..e0f4109e64c6 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h @@ -556,8 +556,7 @@ iwe_stream_add_point(struct iw_request_info *info, char *stream, char *ends, memcpy(stream + lcp_len, ((char *) &iwe->u) + IW_EV_POINT_OFF, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); - if (iwe->u.data.length && extra) - memcpy(stream + point_len, extra, iwe->u.data.length); + memcpy(stream + point_len, extra, iwe->u.data.length); stream += event_len; } return stream; diff --git a/include/net/llc.h b/include/net/llc.h index 82d989995d18..e8e61d4fb458 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -116,11 +116,6 @@ static inline void llc_sap_hold(struct llc_sap *sap) atomic_inc(&sap->refcnt); } -static inline bool llc_sap_hold_safe(struct llc_sap *sap) -{ - return atomic_inc_not_zero(&sap->refcnt); -} - void llc_sap_close(struct llc_sap *sap); static inline void llc_sap_put(struct llc_sap *sap) diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h index df528a623548..fe994d2e5286 100644 --- a/include/net/llc_conn.h +++ b/include/net/llc_conn.h @@ -97,14 +97,13 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb) struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot, int kern); -void llc_sk_stop_all_timers(struct sock *sk, bool sync); void llc_sk_free(struct sock *sk); void llc_sk_reset(struct sock *sk); /* Access to a connection */ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb); -int llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb); +void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb); void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb); void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit); void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ec11cb1c0d80..760bc4d5a2cf 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -975,7 +975,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * @RX_FLAG_DECRYPTED: This frame was decrypted in hardware. * @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame, * verification has been done by the hardware. - * @RX_FLAG_IV_STRIPPED: The IV and ICV are stripped from this frame. + * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame. * If this flag is set, the stack cannot do any replay detection * hence the driver or hardware will have to do that. * @RX_FLAG_PN_VALIDATED: Currently only valid for CCMP/GCMP frames, this @@ -1013,8 +1013,6 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * on this subframe * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC * is stored in the @ampdu_delimiter_crc field) - * @RX_FLAG_MIC_STRIPPED: The mic was stripped of this packet. Decryption was - * done by the hardware * @RX_FLAG_LDPC: LDPC was used * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3 * @RX_FLAG_10MHZ: 10 MHz (half channel) was used @@ -1031,11 +1029,6 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * @RX_FLAG_RADIOTAP_VENDOR_DATA: This frame contains vendor-specific * radiotap data in the skb->data (before the frame) as described by * the &struct ieee80211_vendor_radiotap. - * @RX_FLAG_ALLOW_SAME_PN: Allow the same PN as same packet before. - * This is used for AMSDU subframes which can have the same PN as - * the first subframe. - * @RX_FLAG_ICV_STRIPPED: The ICV is stripped from this frame. CRC checking must - * be done in the hardware. */ enum mac80211_rx_flags { RX_FLAG_MMIC_ERROR = BIT(0), @@ -1066,9 +1059,6 @@ enum mac80211_rx_flags { RX_FLAG_5MHZ = BIT(29), RX_FLAG_AMSDU_MORE = BIT(30), RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(31), - RX_FLAG_MIC_STRIPPED = BIT_ULL(32), - RX_FLAG_ALLOW_SAME_PN = BIT_ULL(33), - RX_FLAG_ICV_STRIPPED = BIT_ULL(34), }; #define RX_FLAG_STBC_SHIFT 26 @@ -1123,7 +1113,7 @@ struct ieee80211_rx_status { u64 mactime; u32 device_timestamp; u32 ampdu_reference; - u64 flag; + u32 flag; u16 freq; u8 vht_flag; u8 rate_idx; @@ -1672,9 +1662,6 @@ struct ieee80211_sta_rates { * @supp_rates: Bitmap of supported rates (per band) * @ht_cap: HT capabilities of this STA; restricted to our own capabilities * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities - * @max_rx_aggregation_subframes: maximal amount of frames in a single AMPDU - * that this station is allowed to transmit to us. - * Can be modified by driver. * @wme: indicates whether the STA supports QoS/WME (if local devices does, * otherwise always false) * @drv_priv: data area for driver use, will always be aligned to @@ -1701,7 +1688,6 @@ struct ieee80211_sta { u16 aid; struct ieee80211_sta_ht_cap ht_cap; struct ieee80211_sta_vht_cap vht_cap; - u8 max_rx_aggregation_subframes; bool wme; u8 uapsd_queues; u8 max_sp; @@ -2687,33 +2673,6 @@ enum ieee80211_ampdu_mlme_action { IEEE80211_AMPDU_TX_OPERATIONAL, }; -/** - * struct ieee80211_ampdu_params - AMPDU action parameters - * - * @action: the ampdu action, value from %ieee80211_ampdu_mlme_action. - * @sta: peer of this AMPDU session - * @tid: tid of the BA session - * @ssn: start sequence number of the session. TX/RX_STOP can pass 0. When - * action is set to %IEEE80211_AMPDU_RX_START the driver passes back the - * actual ssn value used to start the session and writes the value here. - * @buf_size: reorder buffer size (number of subframes). Valid only when the - * action is set to %IEEE80211_AMPDU_RX_START or - * %IEEE80211_AMPDU_TX_OPERATIONAL - * @amsdu: indicates the peer's ability to receive A-MSDU within A-MPDU. - * valid when the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL - * @timeout: BA session timeout. Valid only when the action is set to - * %IEEE80211_AMPDU_RX_START - */ -struct ieee80211_ampdu_params { - enum ieee80211_ampdu_mlme_action action; - struct ieee80211_sta *sta; - u16 tid; - u16 ssn; - u8 buf_size; - bool amsdu; - u16 timeout; -}; - /** * enum ieee80211_frame_release_type - frame release reason * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll @@ -3058,9 +3017,13 @@ enum ieee80211_reconfig_type { * @ampdu_action: Perform a certain A-MPDU action * The RA/TID combination determines the destination and TID we want * the ampdu action to be performed for. The action is defined through - * ieee80211_ampdu_mlme_action. - * When the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL the driver - * may neither send aggregates containing more subframes than @buf_size + * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) + * is the first frame we expect to perform the action on. Notice + * that TX/RX_STOP can pass NULL for this parameter. + * The @buf_size parameter is only valid when the action is set to + * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder + * buffer size (number of subframes) for this session -- the driver + * may neither send aggregates containing more subframes than this * nor send aggregates in a way that lost frames would exceed the * buffer size. If just limiting the aggregate size, this would be * possible with a buf_size of 8: @@ -3071,6 +3034,9 @@ enum ieee80211_reconfig_type { * buffer size of 8. Correct ways to retransmit #1 would be: * - TX: 1 or 18 or 81 * Even "189" would be wrong since 1 could be lost again. + * The @amsdu parameter is valid when the action is set to + * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's ability + * to receive A-MSDU within A-MPDU. * * Returns a negative error code on failure. * The callback can sleep. @@ -3412,7 +3378,9 @@ struct ieee80211_ops { int (*tx_last_beacon)(struct ieee80211_hw *hw); int (*ampdu_action)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params); + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu); int (*get_survey)(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void (*rfkill_poll)(struct ieee80211_hw *hw); @@ -3898,7 +3866,7 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, * The TX headroom reserved by mac80211 for its own tx_status functions. * This is enough for the radiotap header. */ -#define IEEE80211_TX_STATUS_HEADROOM ALIGN(14, 4) +#define IEEE80211_TX_STATUS_HEADROOM 14 /** * ieee80211_sta_set_buffered - inform mac80211 about driver-buffered frames diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 94751e63e656..581d6712bd4d 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -123,7 +123,6 @@ struct net { #endif #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) struct netns_nf_frag nf_frag; - struct ctl_table_header *nf_frag_frags_hdr; #endif struct sock *nfnl; struct sock *nfnl_stash; @@ -218,11 +217,6 @@ int net_eq(const struct net *net1, const struct net *net2) return net1 == net2; } -static inline int check_net(const struct net *net) -{ - return atomic_read(&net->count) != 0; -} - void net_drop_ns(void *); #else @@ -247,11 +241,6 @@ int net_eq(const struct net *net1, const struct net *net2) return 1; } -static inline int check_net(const struct net *net) -{ - return 1; -} - #define net_drop_ns NULL #endif diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h index 0dbce55437f2..9c5638ad872e 100644 --- a/include/net/netfilter/nf_queue.h +++ b/include/net/netfilter/nf_queue.h @@ -28,8 +28,8 @@ struct nf_queue_handler { struct nf_hook_ops *ops); }; -void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh); -void nf_unregister_queue_handler(struct net *net); +void nf_register_queue_handler(const struct nf_queue_handler *qh); +void nf_unregister_queue_handler(void); void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); void nf_queue_entry_get_refs(struct nf_queue_entry *entry); diff --git a/include/net/netlink.h b/include/net/netlink.h index 5ffaea4665f8..0e3172751755 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -745,10 +745,7 @@ static inline int nla_parse_nested(struct nlattr *tb[], int maxtype, */ static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value) { - /* temporary variables to work around GCC PR81715 with asan-stack=1 */ - u8 tmp = value; - - return nla_put(skb, attrtype, sizeof(u8), &tmp); + return nla_put(skb, attrtype, sizeof(u8), &value); } /** @@ -759,9 +756,7 @@ static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value) */ static inline int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value) { - u16 tmp = value; - - return nla_put(skb, attrtype, sizeof(u16), &tmp); + return nla_put(skb, attrtype, sizeof(u16), &value); } /** @@ -772,9 +767,7 @@ static inline int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value) */ static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) { - __be16 tmp = value; - - return nla_put(skb, attrtype, sizeof(__be16), &tmp); + return nla_put(skb, attrtype, sizeof(__be16), &value); } /** @@ -785,9 +778,7 @@ static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) */ static inline int nla_put_net16(struct sk_buff *skb, int attrtype, __be16 value) { - __be16 tmp = value; - - return nla_put_be16(skb, attrtype | NLA_F_NET_BYTEORDER, tmp); + return nla_put_be16(skb, attrtype | NLA_F_NET_BYTEORDER, value); } /** @@ -798,9 +789,7 @@ static inline int nla_put_net16(struct sk_buff *skb, int attrtype, __be16 value) */ static inline int nla_put_le16(struct sk_buff *skb, int attrtype, __le16 value) { - __le16 tmp = value; - - return nla_put(skb, attrtype, sizeof(__le16), &tmp); + return nla_put(skb, attrtype, sizeof(__le16), &value); } /** @@ -811,9 +800,7 @@ static inline int nla_put_le16(struct sk_buff *skb, int attrtype, __le16 value) */ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value) { - u32 tmp = value; - - return nla_put(skb, attrtype, sizeof(u32), &tmp); + return nla_put(skb, attrtype, sizeof(u32), &value); } /** @@ -824,9 +811,7 @@ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value) */ static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value) { - __be32 tmp = value; - - return nla_put(skb, attrtype, sizeof(__be32), &tmp); + return nla_put(skb, attrtype, sizeof(__be32), &value); } /** @@ -837,9 +822,7 @@ static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value) */ static inline int nla_put_net32(struct sk_buff *skb, int attrtype, __be32 value) { - __be32 tmp = value; - - return nla_put_be32(skb, attrtype | NLA_F_NET_BYTEORDER, tmp); + return nla_put_be32(skb, attrtype | NLA_F_NET_BYTEORDER, value); } /** @@ -850,9 +833,7 @@ static inline int nla_put_net32(struct sk_buff *skb, int attrtype, __be32 value) */ static inline int nla_put_le32(struct sk_buff *skb, int attrtype, __le32 value) { - __le32 tmp = value; - - return nla_put(skb, attrtype, sizeof(__le32), &tmp); + return nla_put(skb, attrtype, sizeof(__le32), &value); } /** @@ -863,9 +844,7 @@ static inline int nla_put_le32(struct sk_buff *skb, int attrtype, __le32 value) */ static inline int nla_put_u64(struct sk_buff *skb, int attrtype, u64 value) { - u64 tmp = value; - - return nla_put(skb, attrtype, sizeof(u64), &tmp); + return nla_put(skb, attrtype, sizeof(u64), &value); } /** @@ -876,9 +855,7 @@ static inline int nla_put_u64(struct sk_buff *skb, int attrtype, u64 value) */ static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value) { - __be64 tmp = value; - - return nla_put(skb, attrtype, sizeof(__be64), &tmp); + return nla_put(skb, attrtype, sizeof(__be64), &value); } /** @@ -889,9 +866,7 @@ static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value) */ static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value) { - __be64 tmp = value; - - return nla_put_be64(skb, attrtype | NLA_F_NET_BYTEORDER, tmp); + return nla_put_be64(skb, attrtype | NLA_F_NET_BYTEORDER, value); } /** @@ -902,9 +877,7 @@ static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value) */ static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value) { - __le64 tmp = value; - - return nla_put(skb, attrtype, sizeof(__le64), &tmp); + return nla_put(skb, attrtype, sizeof(__le64), &value); } /** @@ -915,9 +888,7 @@ static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value) */ static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value) { - s8 tmp = value; - - return nla_put(skb, attrtype, sizeof(s8), &tmp); + return nla_put(skb, attrtype, sizeof(s8), &value); } /** @@ -928,9 +899,7 @@ static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value) */ static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value) { - s16 tmp = value; - - return nla_put(skb, attrtype, sizeof(s16), &tmp); + return nla_put(skb, attrtype, sizeof(s16), &value); } /** @@ -941,9 +910,7 @@ static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value) */ static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value) { - s32 tmp = value; - - return nla_put(skb, attrtype, sizeof(s32), &tmp); + return nla_put(skb, attrtype, sizeof(s32), &value); } /** @@ -954,9 +921,7 @@ static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value) */ static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value) { - s64 tmp = value; - - return nla_put(skb, attrtype, sizeof(s64), &tmp); + return nla_put(skb, attrtype, sizeof(s64), &value); } /** @@ -1004,9 +969,7 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype, static inline int nla_put_in_addr(struct sk_buff *skb, int attrtype, __be32 addr) { - __be32 tmp = addr; - - return nla_put_be32(skb, attrtype, tmp); + return nla_put_be32(skb, attrtype, addr); } /** diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index d235722c0d92..c0368db6df54 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h @@ -86,6 +86,7 @@ struct netns_ipv6 { #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) struct netns_nf_frag { + struct netns_sysctl_ipv6 sysctl; struct netns_frags frags; }; #endif diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h index 36d723579af2..38aa4983e2a9 100644 --- a/include/net/netns/netfilter.h +++ b/include/net/netns/netfilter.h @@ -5,13 +5,11 @@ struct proc_dir_entry; struct nf_logger; -struct nf_queue_handler; struct netns_nf { #if defined CONFIG_PROC_FS struct proc_dir_entry *proc_netfilter; #endif - const struct nf_queue_handler __rcu *queue_handler; const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO]; #ifdef CONFIG_SYSCTL struct ctl_table_header *nf_log_dir_header; diff --git a/include/net/nexthop.h b/include/net/nexthop.h index 7fc78663ec9d..3334dbfa5aa4 100644 --- a/include/net/nexthop.h +++ b/include/net/nexthop.h @@ -6,7 +6,7 @@ static inline int rtnh_ok(const struct rtnexthop *rtnh, int remaining) { - return remaining >= (int)sizeof(*rtnh) && + return remaining >= sizeof(*rtnh) && rtnh->rtnh_len >= sizeof(*rtnh) && rtnh->rtnh_len <= remaining; } diff --git a/include/net/red.h b/include/net/red.h index 3618cdfec884..76e0b5f922c6 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -167,17 +167,6 @@ static inline void red_set_vars(struct red_vars *v) v->qcount = -1; } -static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog) -{ - if (fls(qth_min) + Wlog > 32) - return false; - if (fls(qth_max) + Wlog > 32) - return false; - if (qth_max < qth_min) - return false; - return true; -} - static inline void red_set_parms(struct red_parms *p, u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog, u8 Scell_log, u8 *stab, u32 max_P) @@ -189,7 +178,7 @@ static inline void red_set_parms(struct red_parms *p, p->qth_max = qth_max << Wlog; p->Wlog = Wlog; p->Plog = Plog; - if (delta <= 0) + if (delta < 0) delta = 1; p->qth_delta = delta; if (!max_P) { diff --git a/include/net/regulatory.h b/include/net/regulatory.h index f83cacce3308..ebc5a2ed8631 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h @@ -78,7 +78,7 @@ struct regulatory_request { int wiphy_idx; enum nl80211_reg_initiator initiator; enum nl80211_user_reg_hint_type user_reg_hint_type; - char alpha2[3]; + char alpha2[2]; enum nl80211_dfs_regions dfs_region; bool intersect; bool processed; diff --git a/include/net/route.h b/include/net/route.h index 11dfd0df0e67..3adb9c724818 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -64,8 +64,7 @@ struct rtable { __be32 rt_gateway; /* Miscellaneous cached information */ - u32 rt_mtu_locked:1, - rt_pmtu:31; + u32 rt_pmtu; u32 rt_table_id; diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 7a5d6a073165..86df0835f6b5 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -408,15 +408,6 @@ bool tcf_destroy(struct tcf_proto *tp, bool force); void tcf_destroy_chain(struct tcf_proto __rcu **fl); int skb_do_redirect(struct sk_buff *); -static inline bool skb_at_tc_ingress(const struct sk_buff *skb) -{ -#ifdef CONFIG_NET_CLS_ACT - return G_TC_AT(skb->tc_verd) & AT_INGRESS; -#else - return false; -#endif -} - /* Reset all TX qdiscs greater then index of a device. */ static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i) { @@ -717,11 +708,8 @@ static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new, old = *pold; *pold = new; if (old != NULL) { - unsigned int qlen = old->q.qlen; - unsigned int backlog = old->qstats.backlog; - + qdisc_tree_reduce_backlog(old, old->q.qlen, old->qstats.backlog); qdisc_reset(old); - qdisc_tree_reduce_backlog(old, qlen, backlog); } sch_tree_unlock(sch); diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index d33b17ba51d2..ce13cf20f625 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -444,8 +444,6 @@ _sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member) #define _sctp_walk_params(pos, chunk, end, member)\ for (pos.v = chunk->member;\ - (pos.v + offsetof(struct sctp_paramhdr, length) + sizeof(pos.p->length) <=\ - (void *)chunk + end) &&\ pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\ ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\ pos.v += WORD_ROUND(ntohs(pos.p->length))) @@ -456,8 +454,6 @@ _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length)) #define _sctp_walk_errors(err, chunk_hdr, end)\ for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \ sizeof(sctp_chunkhdr_t));\ - ((void *)err + offsetof(sctp_errhdr_t, length) + sizeof(err->length) <=\ - (void *)chunk_hdr + end) &&\ (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\ ntohs(err->length) >= sizeof(sctp_errhdr_t); \ err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length)))) diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index f348c736e6e0..cccdcfd14973 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -141,12 +141,8 @@ __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event); static inline int sctp_ulpevent_type_enabled(__u16 sn_type, struct sctp_event_subscribe *mask) { - int offset = sn_type - SCTP_SN_TYPE_BASE; char *amask = (char *) mask; - - if (offset >= sizeof(struct sctp_event_subscribe)) - return 0; - return amask[offset]; + return amask[sn_type - SCTP_SN_TYPE_BASE]; } /* Given an event subscription, is this event enabled? */ diff --git a/include/net/slhc_vj.h b/include/net/slhc_vj.h index 8fcf8908a694..8716d5942b65 100644 --- a/include/net/slhc_vj.h +++ b/include/net/slhc_vj.h @@ -127,7 +127,6 @@ typedef __u32 int32; */ struct cstate { byte_t cs_this; /* connection id number (xmit) */ - bool initialized; /* true if initialized */ struct cstate *next; /* next in ring (xmit) */ struct iphdr cs_ip; /* ip/tcp hdr from most recent packet */ struct tcphdr cs_tcp; diff --git a/include/net/sock.h b/include/net/sock.h index 5749977ec4a2..73334d1f7a39 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1454,16 +1454,6 @@ static inline void sk_mem_uncharge(struct sock *sk, int size) if (!sk_has_account(sk)) return; sk->sk_forward_alloc += size; - - /* Avoid a possible overflow. - * TCP send queues can make this happen, if sk_mem_reclaim() - * is not called and more than 2 GBytes are released at once. - * - * If we reach 2 MBytes, reclaim 1 MBytes right now, there is - * no need to hold that much forward allocation anyway. - */ - if (unlikely(sk->sk_forward_alloc >= 1 << 21)) - __sk_mem_reclaim(sk, 1 << 20); } static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 31d0e5143848..1d22ce9f352e 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -88,7 +88,7 @@ struct switchdev_obj_ipv4_fib { struct switchdev_obj obj; u32 dst; int dst_len; - struct fib_info *fi; + struct fib_info fi; u8 tos; u8 type; u32 nlflags; diff --git a/include/net/tcp.h b/include/net/tcp.h index 85c1a0e8d3cb..30c100524abb 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -251,8 +251,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo); #define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */ #define FLAG_SACK_RENEGING 0x2000 /* snd_una advanced to a sacked seq */ #define FLAG_UPDATE_TS_RECENT 0x4000 /* tcp_replace_ts_recent() */ - #define FLAG_NO_CHALLENGE_ACK 0x8000 /* do not call tcp_send_challenge_ack() */ - #define MPTCP_FLAG_DATA_ACKED 0x10000 + #define MPTCP_FLAG_DATA_ACKED 0x8000 #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) @@ -388,6 +387,7 @@ struct mptcp_options_received; void tcp_cleanup_rbuf(struct sock *sk, int copied); void tcp_cwnd_validate(struct sock *sk, bool is_cwnd_limited); +void tcp_enter_quickack_mode(struct sock *sk); int tcp_close_state(struct sock *sk); void tcp_minshall_update(struct tcp_sock *tp, unsigned int mss_now, const struct sk_buff *skb); @@ -406,7 +406,7 @@ bool tcp_snd_wnd_test(const struct tcp_sock *tp, const struct sk_buff *skb, unsigned int cur_mss); unsigned int tcp_cwnd_test(const struct tcp_sock *tp, const struct sk_buff *skb); int tcp_init_tso_segs(struct sk_buff *skb, unsigned int mss_now); -int __pskb_trim_head(struct sk_buff *skb, int len); +void __pskb_trim_head(struct sk_buff *skb, int len); void tcp_queue_skb(struct sock *sk, struct sk_buff *skb); void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags); void tcp_reset(struct sock *sk); @@ -499,7 +499,6 @@ ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags); -void tcp_enter_quickack_mode(struct sock *sk, unsigned int max_quickacks); static inline void tcp_dec_quickack_mode(struct sock *sk, const unsigned int pkts) { @@ -703,7 +702,6 @@ void tcp_send_fin(struct sock *sk); void tcp_send_active_reset(struct sock *sk, gfp_t priority); int tcp_send_synack(struct sock *); void tcp_push_one(struct sock *, unsigned int mss_now); -void __tcp_send_ack(struct sock *sk, u32 rcv_nxt); void tcp_send_ack(struct sock *sk); void tcp_send_delayed_ack(struct sock *sk); void tcp_send_loss_probe(struct sock *sk); @@ -993,6 +991,8 @@ enum tcp_ca_event { CA_EVENT_LOSS, /* loss timeout */ CA_EVENT_ECN_NO_CE, /* ECT set, but not CE marked */ CA_EVENT_ECN_IS_CE, /* received CE marked IP packet */ + CA_EVENT_DELAYED_ACK, /* Delayed ack is sent */ + CA_EVENT_NON_DELAYED_ACK, }; /* Information about inbound ACK, passed to cong_ops->in_ack_event() */ @@ -1328,7 +1328,6 @@ static inline void tcp_prequeue_init(struct tcp_sock *tp) } bool tcp_prequeue(struct sock *sk, struct sk_buff *skb); -int tcp_filter(struct sock *sk, struct sk_buff *skb); #undef STATE_TRACE @@ -1387,11 +1386,9 @@ static inline int tcp_space_from_win(int win) static inline int tcp_win_from_space(int space) { - int tcp_adv_win_scale = sysctl_tcp_adv_win_scale; - - return tcp_adv_win_scale <= 0 ? - (space>>(-tcp_adv_win_scale)) : - space - (space>>tcp_adv_win_scale); + return sysctl_tcp_adv_win_scale<=0 ? + (space>>(-sysctl_tcp_adv_win_scale)) : + space - (space>>sysctl_tcp_adv_win_scale); } #ifdef CONFIG_MPTCP extern struct static_key mptcp_static_key; @@ -1814,12 +1811,12 @@ static inline void tcp_highest_sack_reset(struct sock *sk) tcp_sk(sk)->highest_sack = tcp_write_queue_head(sk); } -/* Called when old skb is about to be deleted and replaced by new skb */ -static inline void tcp_highest_sack_replace(struct sock *sk, +/* Called when old skb is about to be deleted (to be combined with new skb) */ +static inline void tcp_highest_sack_combine(struct sock *sk, struct sk_buff *old, struct sk_buff *new) { - if (old == tcp_highest_sack(sk)) + if (tcp_sk(sk)->sacked_out && (old == tcp_sk(sk)->highest_sack)) tcp_sk(sk)->highest_sack = new; } diff --git a/include/net/udplite.h b/include/net/udplite.h index 8228155b305e..80761938b9a7 100644 --- a/include/net/udplite.h +++ b/include/net/udplite.h @@ -62,7 +62,6 @@ static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh) UDP_SKB_CB(skb)->cscov = cscov; if (skb->ip_summed == CHECKSUM_COMPLETE) skb->ip_summed = CHECKSUM_NONE; - skb->csum_valid = 0; } return 0; diff --git a/include/net/x25.h b/include/net/x25.h index 6d30a01d281d..c383aa4edbf0 100644 --- a/include/net/x25.h +++ b/include/net/x25.h @@ -298,10 +298,10 @@ void x25_check_rbuf(struct sock *); /* sysctl_net_x25.c */ #ifdef CONFIG_SYSCTL -int x25_register_sysctl(void); +void x25_register_sysctl(void); void x25_unregister_sysctl(void); #else -static inline int x25_register_sysctl(void) { return 0; }; +static inline void x25_register_sysctl(void) {}; static inline void x25_unregister_sysctl(void) {}; #endif /* CONFIG_SYSCTL */ diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 5901b67e3fa3..b4a2c4ab16b7 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -950,6 +950,10 @@ struct xfrm_dst { struct flow_cache_object flo; struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; int num_pols, num_xfrms; +#ifdef CONFIG_XFRM_SUB_POLICY + struct flowi *origin; + struct xfrm_selector *partner; +#endif u32 xfrm_genid; u32 policy_genid; u32 route_mtu_cached; @@ -965,6 +969,12 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) dst_release(xdst->route); if (likely(xdst->u.dst.xfrm)) xfrm_state_put(xdst->u.dst.xfrm); +#ifdef CONFIG_XFRM_SUB_POLICY + kfree(xdst->origin); + xdst->origin = NULL; + kfree(xdst->partner); + xdst->partner = NULL; +#endif } #endif diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h index 0dba4e4ed2be..f095155d8749 100644 --- a/include/uapi/linux/netlink.h +++ b/include/uapi/linux/netlink.h @@ -107,10 +107,8 @@ struct nlmsgerr { #define NETLINK_PKTINFO 3 #define NETLINK_BROADCAST_ERROR 4 #define NETLINK_NO_ENOBUFS 5 -#ifndef __KERNEL__ #define NETLINK_RX_RING 6 #define NETLINK_TX_RING 7 -#endif #define NETLINK_LISTEN_ALL_NSID 8 #define NETLINK_LIST_MEMBERSHIPS 9 #define NETLINK_CAP_ACK 10 @@ -136,7 +134,6 @@ struct nl_mmap_hdr { __u32 nm_gid; }; -#ifndef __KERNEL__ enum nl_mmap_status { NL_MMAP_STATUS_UNUSED, NL_MMAP_STATUS_RESERVED, @@ -148,7 +145,6 @@ enum nl_mmap_status { #define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO #define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT) #define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr)) -#endif #define NET_MAJOR 36 /* Major 36 is reserved for networking */ diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index e2713b0794ae..d2cd9de4b724 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -111,7 +111,12 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) vlan_gvrp_uninit_applicant(real_dev); } - vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id); + /* Take it out of our own structures, but be sure to interlock with + * HW accelerating devices or SW vlan input packet processing if + * VLAN is not 0 (leave it there for 802.1p). + */ + if (vlan_id) + vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id); /* Get rid of the vlan's reference to real_dev */ dev_put(real_dev); @@ -273,8 +278,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) return 0; out_free_newdev: - if (new_dev->reg_state == NETREG_UNINITIALIZED) - free_netdev(new_dev); + free_netdev(new_dev); return err; } @@ -287,10 +291,6 @@ static void vlan_sync_address(struct net_device *dev, if (ether_addr_equal(vlan->real_dev_addr, dev->dev_addr)) return; - /* vlan continues to inherit address of lower device */ - if (vlan_dev_inherit_address(vlandev, dev)) - goto out; - /* vlan address was different from the old address and is equal to * the new address */ if (!ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) && @@ -303,7 +303,6 @@ static void vlan_sync_address(struct net_device *dev, !ether_addr_equal(vlandev->dev_addr, dev->dev_addr)) dev_uc_add(dev, vlandev->dev_addr); -out: ether_addr_copy(vlan->real_dev_addr, dev->dev_addr); } @@ -371,9 +370,6 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, dev->name); vlan_vid_add(dev, htons(ETH_P_8021Q), 0); } - if (event == NETDEV_DOWN && - (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) - vlan_vid_del(dev, htons(ETH_P_8021Q), 0); vlan_info = rtnl_dereference(dev->vlan_info); if (!vlan_info) @@ -421,6 +417,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, struct net_device *tmp; LIST_HEAD(close_list); + if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) + vlan_vid_del(dev, htons(ETH_P_8021Q), 0); + /* Put all VLANs for this dev in the down state too. */ vlan_group_for_each_dev(grp, i, vlandev) { flgs = vlandev->flags; @@ -660,7 +659,7 @@ static struct sk_buff **vlan_gro_receive(struct sk_buff **head, skb_gro_pull(skb, sizeof(*vhdr)); skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr)); - pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); + pp = ptype->callbacks.gro_receive(head, skb); out_unlock: rcu_read_unlock(); diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index cc1557978066..9d010a09ab98 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -109,8 +109,6 @@ int vlan_check_real_dev(struct net_device *real_dev, void vlan_setup(struct net_device *dev); int register_vlan_dev(struct net_device *dev); void unregister_vlan_dev(struct net_device *dev, struct list_head *head); -bool vlan_dev_inherit_address(struct net_device *dev, - struct net_device *real_dev); static inline u32 vlan_get_ingress_priority(struct net_device *dev, u16 vlan_tci) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index ac9791dd4768..fded86508117 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include "vlan.h" @@ -245,17 +244,6 @@ void vlan_dev_get_realdev_name(const struct net_device *dev, char *result) strncpy(result, vlan_dev_priv(dev)->real_dev->name, 23); } -bool vlan_dev_inherit_address(struct net_device *dev, - struct net_device *real_dev) -{ - if (dev->addr_assign_type != NET_ADDR_STOLEN) - return false; - - ether_addr_copy(dev->dev_addr, real_dev->dev_addr); - call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); - return true; -} - static int vlan_dev_open(struct net_device *dev) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); @@ -266,8 +254,7 @@ static int vlan_dev_open(struct net_device *dev) !(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) return -ENETDOWN; - if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr) && - !vlan_dev_inherit_address(dev, real_dev)) { + if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) { err = dev_uc_add(real_dev, dev->dev_addr); if (err < 0) goto out; @@ -560,7 +547,8 @@ static int vlan_dev_init(struct net_device *dev) NETIF_F_HIGHDMA | NETIF_F_SCTP_CSUM | NETIF_F_ALL_FCOE; - dev->features |= dev->hw_features | NETIF_F_LLTX; + dev->features |= real_dev->vlan_features | NETIF_F_LLTX | + NETIF_F_GSO_SOFTWARE; dev->gso_max_size = real_dev->gso_max_size; if (dev->features & NETIF_F_VLAN_FEATURES) netdev_warn(real_dev, "VLAN features are set incorrectly. Q-in-Q configurations may not work correctly.\n"); @@ -570,10 +558,8 @@ static int vlan_dev_init(struct net_device *dev) /* ipv6 shared card related stuff */ dev->dev_id = real_dev->dev_id; - if (is_zero_ether_addr(dev->dev_addr)) { - ether_addr_copy(dev->dev_addr, real_dev->dev_addr); - dev->addr_assign_type = NET_ADDR_STOLEN; - } + if (is_zero_ether_addr(dev->dev_addr)) + eth_hw_addr_inherit(dev, real_dev); if (is_zero_ether_addr(dev->broadcast)) memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len); @@ -655,11 +641,8 @@ static int vlan_ethtool_get_ts_info(struct net_device *dev, { const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); const struct ethtool_ops *ops = vlan->real_dev->ethtool_ops; - struct phy_device *phydev = vlan->real_dev->phydev; - if (phydev && phydev->drv && phydev->drv->ts_info) { - return phydev->drv->ts_info(phydev, info); - } else if (ops->get_ts_info) { + if (ops->get_ts_info) { return ops->get_ts_info(vlan->real_dev, info); } else { info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | diff --git a/net/9p/client.c b/net/9p/client.c index 3ff26eb1ea20..ea79ee9a7348 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -749,7 +749,8 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) } again: /* Wait for the response */ - err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD); + err = wait_event_interruptible(*req->wq, + req->status >= REQ_STATUS_RCVD); /* * Make sure our req is coherent with regard to updates in other @@ -2100,10 +2101,6 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) trace_9p_protocol_dump(clnt, req->rc); goto free_and_error; } - if (rsize < count) { - pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize); - count = rsize; - } p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count); diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 2ddeecca5b12..6e70ddb158b4 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -290,8 +290,8 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) if (err == -ENOSPC) { chan->ring_bufs_avail = 0; spin_unlock_irqrestore(&chan->lock, flags); - err = wait_event_killable(*chan->vc_wq, - chan->ring_bufs_avail); + err = wait_event_interruptible(*chan->vc_wq, + chan->ring_bufs_avail); if (err == -ERESTARTSYS) return err; @@ -331,7 +331,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, * Other zc request to finish here */ if (atomic_read(&vp_pinned) >= chan->p9_max_pages) { - err = wait_event_killable(vp_wq, + err = wait_event_interruptible(vp_wq, (atomic_read(&vp_pinned) < chan->p9_max_pages)); if (err == -ERESTARTSYS) return err; @@ -475,8 +475,8 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, if (err == -ENOSPC) { chan->ring_bufs_avail = 0; spin_unlock_irqrestore(&chan->lock, flags); - err = wait_event_killable(*chan->vc_wq, - chan->ring_bufs_avail); + err = wait_event_interruptible(*chan->vc_wq, + chan->ring_bufs_avail); if (err == -ERESTARTSYS) goto err_out; @@ -493,7 +493,8 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, virtqueue_kick(chan->vq); spin_unlock_irqrestore(&chan->lock, flags); p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); - err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD); + err = wait_event_interruptible(*req->wq, + req->status >= REQ_STATUS_RCVD); /* * Non kernel buffers are pinned, unpin them */ diff --git a/net/Kconfig b/net/Kconfig index 30c896ab01ae..42fe603bbfdb 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -394,19 +394,12 @@ config LWTUNNEL weight tunnel endpoint. Tunnel encapsulation parameters are stored with light weight tunnel state associated with fib routes. -config DST_CACHE - bool - default n - endif # if NET # Used by archs to tell that they support BPF_JIT config HAVE_BPF_JIT bool -config HAVE_EBPF_JIT - bool - # Cross Layer TCP config CLTCP bool "Cross Layer TCP" diff --git a/net/atm/lec.c b/net/atm/lec.c index 10e4066991b8..cd3b37989057 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -41,9 +41,6 @@ static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 }; #include #include -/* Hardening for Spectre-v1 */ -#include - #include "lec.h" #include "lec_arpc.h" #include "resources.h" @@ -700,10 +697,8 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg) bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc)); if (bytes_left != 0) pr_info("copy from user failed for %d bytes\n", bytes_left); - if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF) - return -EINVAL; - ioc_data.dev_num = array_index_nospec(ioc_data.dev_num, MAX_LEC_ITF); - if (!dev_lec[ioc_data.dev_num]) + if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF || + !dev_lec[ioc_data.dev_num]) return -EINVAL; vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL); if (!vpriv) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 2fdebabbfacd..fbd0acf80b13 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -976,8 +976,7 @@ static int ax25_release(struct socket *sock) release_sock(sk); ax25_disconnect(ax25, 0); lock_sock(sk); - if (!sock_flag(ax25->sk, SOCK_DESTROY)) - ax25_destroy_socket(ax25); + ax25_destroy_socket(ax25); break; case AX25_STATE_3: diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c index 5237dff6941d..951cd57bb07d 100644 --- a/net/ax25/ax25_ds_timer.c +++ b/net/ax25/ax25_ds_timer.c @@ -102,7 +102,6 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25) switch (ax25->state) { case AX25_STATE_0: - case AX25_STATE_2: /* Magic here: If we listen() and a new link dies before it is accepted() it isn't 'dead' so doesn't get removed. */ if (!sk || sock_flag(sk, SOCK_DESTROY) || @@ -112,7 +111,6 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25) sock_hold(sk); ax25_destroy_socket(ax25); bh_unlock_sock(sk); - /* Ungrab socket and destroy it */ sock_put(sk); } else ax25_destroy_socket(ax25); @@ -215,8 +213,7 @@ void ax25_ds_t1_timeout(ax25_cb *ax25) case AX25_STATE_2: if (ax25->n2count == ax25->n2) { ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); - if (!sock_flag(ax25->sk, SOCK_DESTROY)) - ax25_disconnect(ax25, ETIMEDOUT); + ax25_disconnect(ax25, ETIMEDOUT); return; } else { ax25->n2count++; diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c index 2c0d6ef66f9d..004467c9e6e1 100644 --- a/net/ax25/ax25_std_timer.c +++ b/net/ax25/ax25_std_timer.c @@ -38,7 +38,6 @@ void ax25_std_heartbeat_expiry(ax25_cb *ax25) switch (ax25->state) { case AX25_STATE_0: - case AX25_STATE_2: /* Magic here: If we listen() and a new link dies before it is accepted() it isn't 'dead' so doesn't get removed. */ if (!sk || sock_flag(sk, SOCK_DESTROY) || @@ -48,7 +47,6 @@ void ax25_std_heartbeat_expiry(ax25_cb *ax25) sock_hold(sk); ax25_destroy_socket(ax25); bh_unlock_sock(sk); - /* Ungrab socket and destroy it */ sock_put(sk); } else ax25_destroy_socket(ax25); @@ -146,8 +144,7 @@ void ax25_std_t1timer_expiry(ax25_cb *ax25) case AX25_STATE_2: if (ax25->n2count == ax25->n2) { ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); - if (!sock_flag(ax25->sk, SOCK_DESTROY)) - ax25_disconnect(ax25, ETIMEDOUT); + ax25_disconnect(ax25, ETIMEDOUT); return; } else { ax25->n2count++; diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c index 983f0b5e14f1..3b78e8473a01 100644 --- a/net/ax25/ax25_subr.c +++ b/net/ax25/ax25_subr.c @@ -264,8 +264,7 @@ void ax25_disconnect(ax25_cb *ax25, int reason) { ax25_clear_queues(ax25); - if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY)) - ax25_stop_heartbeat(ax25); + ax25_stop_heartbeat(ax25); ax25_stop_t1timer(ax25); ax25_stop_t2timer(ax25); ax25_stop_t3timer(ax25); diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index c5208136e3fc..f5d2fe5e31cc 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -1603,22 +1603,10 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, /* if yes, the client has roamed and we have * to unclaim it. */ - if (batadv_has_timed_out(claim->lasttime, 100)) { - /* only unclaim if the last claim entry is - * older than 100 ms to make sure we really - * have a roaming client here. - */ - batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_tx(): Roaming client %pM detected. Unclaim it.\n", - ethhdr->h_source); - batadv_handle_unclaim(bat_priv, primary_if, - primary_if->net_dev->dev_addr, - ethhdr->h_source, vid); - goto allow; - } else { - batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_tx(): Race for claim %pM detected. Drop packet.\n", - ethhdr->h_source); - goto handled; - } + batadv_handle_unclaim(bat_priv, primary_if, + primary_if->net_dev->dev_addr, + ethhdr->h_source, vid); + goto allow; } /* check if it is a multicast/broadcast frame */ diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index c2dff7c6e960..5f19133c5530 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -374,7 +374,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, batadv_arp_hw_src(skb, hdr_size), &ip_src, batadv_arp_hw_dst(skb, hdr_size), &ip_dst); - if (hdr_size < sizeof(struct batadv_unicast_packet)) + if (hdr_size == 0) return; unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 5d2f9d4879b2..700c96c82a15 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -278,8 +278,7 @@ batadv_frag_merge_packets(struct hlist_head *chain) /* Move the existing MAC header to just before the payload. (Override * the fragment header.) */ - skb_pull(skb_out, hdr_size); - skb_out->ip_summed = CHECKSUM_NONE; + skb_pull_rcsum(skb_out, hdr_size); memmove(skb_out->data - ETH_HLEN, skb_mac_header(skb_out), ETH_HLEN); skb_set_mac_header(skb_out, -ETH_HLEN); skb_reset_network_header(skb_out); diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 6abfba1e227f..e6c8382c79ba 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -798,9 +798,6 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, vid = batadv_get_vid(skb, 0); - if (is_multicast_ether_addr(ethhdr->h_dest)) - goto out; - orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source, ethhdr->h_dest, vid); if (!orig_dst_node) diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index 8aa2d65df86f..eb76386f8d4b 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@ -428,8 +428,8 @@ static struct batadv_orig_node * batadv_mcast_forw_tt_node_get(struct batadv_priv *bat_priv, struct ethhdr *ethhdr) { - return batadv_transtable_search(bat_priv, NULL, ethhdr->h_dest, - BATADV_NO_FLAGS); + return batadv_transtable_search(bat_priv, ethhdr->h_source, + ethhdr->h_dest, BATADV_NO_FLAGS); } /** diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 6282f021ddfb..17851d3aaf22 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -197,12 +197,18 @@ static void batadv_neigh_node_release(struct batadv_neigh_node *neigh_node) { struct hlist_node *node_tmp; struct batadv_neigh_ifinfo *neigh_ifinfo; + struct batadv_algo_ops *bao; + + bao = neigh_node->orig_node->bat_priv->bat_algo_ops; hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, &neigh_node->ifinfo_list, list) { batadv_neigh_ifinfo_free_ref(neigh_ifinfo); } + if (bao->bat_neigh_free) + bao->bat_neigh_free(neigh_node); + batadv_hardif_free_ref(neigh_node->if_incoming); kfree_rcu(neigh_node, rcu); diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 9f1fe6169bef..720f1a5b81ac 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -430,7 +430,13 @@ void batadv_interface_rx(struct net_device *soft_iface, /* skb->dev & skb->pkt_type are set here */ skb->protocol = eth_type_trans(skb, soft_iface); - skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + + /* should not be necessary anymore as we use skb_pull_rcsum() + * TODO: please verify this and remove this TODO + * -- Dec 21st 2009, Simon Wunderlich + */ + + /* skb->ip_summed = CHECKSUM_UNNECESSARY; */ batadv_inc_counter(bat_priv, BATADV_CNT_RX); batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index f2079acb555d..83b0ca27a45e 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -2764,7 +2764,7 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv, &tvlv_tt_data, &tt_change, &tt_len); - if (!tt_len || !tvlv_len) + if (!tt_len) goto unlock; /* Copy the last orig_node's OGM buffer */ @@ -2782,7 +2782,7 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv, &tvlv_tt_data, &tt_change, &tt_len); - if (!tt_len || !tvlv_len) + if (!tt_len) goto out; /* fill the rest of the tvlv with the real TT entries */ diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index cbd347c2e4a5..d260efd70499 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1136,6 +1136,8 @@ struct batadv_forw_packet { * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or better * than neigh2 for their respective outgoing interface from the metric * prospective + * @bat_neigh_free: free the resources allocated by the routing algorithm for a + * neigh_node object * @bat_orig_print: print the originator table (optional) * @bat_orig_free: free the resources allocated by the routing algorithm for an * orig_node object @@ -1163,6 +1165,7 @@ struct batadv_algo_ops { struct batadv_hard_iface *if_outgoing1, struct batadv_neigh_node *neigh2, struct batadv_hard_iface *if_outgoing2); + void (*bat_neigh_free)(struct batadv_neigh_node *neigh); /* orig_node handling API */ void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, struct batadv_hard_iface *hard_iface); diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 69f56073b337..1641367e54ca 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -484,16 +484,16 @@ static int bnep_session(void *arg) struct net_device *dev = s->dev; struct sock *sk = s->sock->sk; struct sk_buff *skb; - DEFINE_WAIT_FUNC(wait, woken_wake_function); + wait_queue_t wait; BT_DBG(""); set_user_nice(current, -15); + init_waitqueue_entry(&wait, current); add_wait_queue(sk_sleep(sk), &wait); while (1) { - /* Ensure session->terminate is updated */ - smp_mb__before_atomic(); + set_current_state(TASK_INTERRUPTIBLE); if (atomic_read(&s->terminate)) break; @@ -515,8 +515,9 @@ static int bnep_session(void *arg) break; netif_wake_queue(dev); - wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); + schedule(); } + __set_current_state(TASK_RUNNING); remove_wait_queue(sk_sleep(sk), &wait); /* Cleanup session */ @@ -662,7 +663,7 @@ int bnep_del_connection(struct bnep_conndel_req *req) s = __bnep_get_session(req->dst); if (s) { atomic_inc(&s->terminate); - wake_up_interruptible(sk_sleep(s->sock->sk)); + wake_up_process(s->task); } else err = -ENOENT; diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 3a39fd523e40..298ed37010e6 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -281,16 +281,16 @@ static int cmtp_session(void *arg) struct cmtp_session *session = arg; struct sock *sk = session->sock->sk; struct sk_buff *skb; - DEFINE_WAIT_FUNC(wait, woken_wake_function); + wait_queue_t wait; BT_DBG("session %p", session); set_user_nice(current, -15); + init_waitqueue_entry(&wait, current); add_wait_queue(sk_sleep(sk), &wait); while (1) { - /* Ensure session->terminate is updated */ - smp_mb__before_atomic(); + set_current_state(TASK_INTERRUPTIBLE); if (atomic_read(&session->terminate)) break; @@ -307,8 +307,9 @@ static int cmtp_session(void *arg) cmtp_process_transmit(session); - wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); + schedule(); } + __set_current_state(TASK_RUNNING); remove_wait_queue(sk_sleep(sk), &wait); down_write(&cmtp_session_sem); @@ -393,7 +394,7 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) err = cmtp_attach_device(session); if (err < 0) { atomic_inc(&session->terminate); - wake_up_interruptible(sk_sleep(session->sock->sk)); + wake_up_process(session->task); up_write(&cmtp_session_sem); return err; } @@ -431,11 +432,7 @@ int cmtp_del_connection(struct cmtp_conndel_req *req) /* Stop session thread */ atomic_inc(&session->terminate); - - /* Ensure session->terminate is updated */ - smp_mb__after_atomic(); - - wake_up_interruptible(sk_sleep(session->sock->sk)); + wake_up_process(session->task); } else err = -ENOENT; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 80be0ee17ff3..24e9410923d0 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -708,8 +708,7 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode) } static void hci_req_add_le_create_conn(struct hci_request *req, - struct hci_conn *conn, - bdaddr_t *direct_rpa) + struct hci_conn *conn) { struct hci_cp_le_create_conn cp; struct hci_dev *hdev = conn->hdev; @@ -717,23 +716,11 @@ static void hci_req_add_le_create_conn(struct hci_request *req, memset(&cp, 0, sizeof(cp)); - /* If direct address was provided we use it instead of current - * address. + /* Update random address, but set require_privacy to false so + * that we never connect with an non-resolvable address. */ - if (direct_rpa) { - if (bacmp(&req->hdev->random_addr, direct_rpa)) - hci_req_add(req, HCI_OP_LE_SET_RANDOM_ADDR, 6, - direct_rpa); - - /* direct address is always RPA */ - own_addr_type = ADDR_LE_DEV_RANDOM; - } else { - /* Update random address, but set require_privacy to false so - * that we never connect with an non-resolvable address. - */ - if (hci_update_random_address(req, false, &own_addr_type)) - return; - } + if (hci_update_random_address(req, false, &own_addr_type)) + return; /* Set window to be the same value as the interval to enable * continuous scanning. @@ -795,7 +782,7 @@ static void hci_req_directed_advertising(struct hci_request *req, struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u16 conn_timeout, - u8 role, bdaddr_t *direct_rpa) + u8 role) { struct hci_conn_params *params; struct hci_conn *conn, *conn_unfinished; @@ -926,7 +913,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED); } - hci_req_add_le_create_conn(&req, conn, direct_rpa); + hci_req_add_le_create_conn(&req, conn); create_conn: err = hci_req_run(&req, create_le_conn_complete); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 5d0b1358c754..62edbf1b114e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -716,7 +716,6 @@ static void hci_set_event_mask_page_2(struct hci_request *req) { struct hci_dev *hdev = req->hdev; u8 events[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - bool changed = false; /* If Connectionless Slave Broadcast master role is supported * enable all necessary events for it. @@ -726,7 +725,6 @@ static void hci_set_event_mask_page_2(struct hci_request *req) events[1] |= 0x80; /* Synchronization Train Complete */ events[2] |= 0x10; /* Slave Page Response Timeout */ events[2] |= 0x20; /* CSB Channel Map Change */ - changed = true; } /* If Connectionless Slave Broadcast slave role is supported @@ -737,24 +735,13 @@ static void hci_set_event_mask_page_2(struct hci_request *req) events[2] |= 0x02; /* CSB Receive */ events[2] |= 0x04; /* CSB Timeout */ events[2] |= 0x08; /* Truncated Page Complete */ - changed = true; } /* Enable Authenticated Payload Timeout Expired event if supported */ - if (lmp_ping_capable(hdev) || hdev->le_features[0] & HCI_LE_PING) { + if (lmp_ping_capable(hdev) || hdev->le_features[0] & HCI_LE_PING) events[2] |= 0x80; - changed = true; - } - /* Some Broadcom based controllers indicate support for Set Event - * Mask Page 2 command, but then actually do not support it. Since - * the default value is all bits set to zero, the command is only - * required if the event mask has to be changed. In case no change - * to the event mask is needed, skip this command. - */ - if (changed) - hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, - sizeof(events), events); + hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events); } static void hci_init3_req(struct hci_request *req, unsigned long opt) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d40d32a2c12d..d57c11c1c6b5 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4632,8 +4632,7 @@ static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, /* This function requires the caller holds hdev->lock */ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, - u8 addr_type, u8 adv_type, - bdaddr_t *direct_rpa) + u8 addr_type, u8 adv_type) { struct hci_conn *conn; struct hci_conn_params *params; @@ -4684,8 +4683,7 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev, } conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, - HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER, - direct_rpa); + HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); if (!IS_ERR(conn)) { /* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned * by higher layer that tried to connect, if no then @@ -4782,13 +4780,8 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, bdaddr_type = irk->addr_type; } - /* Check if we have been requested to connect to this device. - * - * direct_addr is set only for directed advertising reports (it is NULL - * for advertising reports) and is already verified to be RPA above. - */ - conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type, - direct_addr); + /* Check if we have been requested to connect to this device */ + conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type); if (conn && type == LE_ADV_IND) { /* Store report for later inclusion by * mgmt_device_connected diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index c842f40c1173..b1eb8c09a660 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -1164,8 +1164,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; - if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE| - MSG_CMSG_COMPAT)) + if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) return -EINVAL; if (len < 4 || len > HCI_MAX_FRAME_SIZE) diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 1811f8e7ddf4..0bec4588c3c8 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -36,7 +36,6 @@ #define VERSION "1.2" static DECLARE_RWSEM(hidp_session_sem); -static DECLARE_WAIT_QUEUE_HEAD(hidp_session_wq); static LIST_HEAD(hidp_session_list); static unsigned char hidp_keycode[256] = { @@ -431,8 +430,8 @@ static void hidp_del_timer(struct hidp_session *session) del_timer(&session->timer); } -static void hidp_process_report(struct hidp_session *session, int type, - const u8 *data, unsigned int len, int intr) +static void hidp_process_report(struct hidp_session *session, + int type, const u8 *data, int len, int intr) { if (len > HID_MAX_BUFFER_SIZE) len = HID_MAX_BUFFER_SIZE; @@ -1069,12 +1068,12 @@ static int hidp_session_start_sync(struct hidp_session *session) * Wake up session thread and notify it to stop. This is asynchronous and * returns immediately. Call this whenever a runtime error occurs and you want * the session to stop. - * Note: wake_up_interruptible() performs any necessary memory-barriers for us. + * Note: wake_up_process() performs any necessary memory-barriers for us. */ static void hidp_session_terminate(struct hidp_session *session) { atomic_inc(&session->terminate); - wake_up_interruptible(&hidp_session_wq); + wake_up_process(session->task); } /* @@ -1181,9 +1180,7 @@ static void hidp_session_run(struct hidp_session *session) struct sock *ctrl_sk = session->ctrl_sock->sk; struct sock *intr_sk = session->intr_sock->sk; struct sk_buff *skb; - DEFINE_WAIT_FUNC(wait, woken_wake_function); - add_wait_queue(&hidp_session_wq, &wait); for (;;) { /* * This thread can be woken up two ways: @@ -1191,10 +1188,12 @@ static void hidp_session_run(struct hidp_session *session) * session->terminate flag and wakes this thread up. * - Via modifying the socket state of ctrl/intr_sock. This * thread is woken up by ->sk_state_changed(). + * + * Note: set_current_state() performs any necessary + * memory-barriers for us. */ + set_current_state(TASK_INTERRUPTIBLE); - /* Ensure session->terminate is updated */ - smp_mb__before_atomic(); if (atomic_read(&session->terminate)) break; @@ -1228,22 +1227,11 @@ static void hidp_session_run(struct hidp_session *session) hidp_process_transmit(session, &session->ctrl_transmit, session->ctrl_sock); - wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); + schedule(); } - remove_wait_queue(&hidp_session_wq, &wait); atomic_inc(&session->terminate); - - /* Ensure session->terminate is updated */ - smp_mb__after_atomic(); -} - -static int hidp_session_wake_function(wait_queue_t *wait, - unsigned int mode, - int sync, void *key) -{ - wake_up_interruptible(&hidp_session_wq); - return false; + set_current_state(TASK_RUNNING); } /* @@ -1256,8 +1244,7 @@ static int hidp_session_wake_function(wait_queue_t *wait, static int hidp_session_thread(void *arg) { struct hidp_session *session = arg; - DEFINE_WAIT_FUNC(ctrl_wait, hidp_session_wake_function); - DEFINE_WAIT_FUNC(intr_wait, hidp_session_wake_function); + wait_queue_t ctrl_wait, intr_wait; BT_DBG("session %p", session); @@ -1267,6 +1254,8 @@ static int hidp_session_thread(void *arg) set_user_nice(current, -15); hidp_set_timer(session); + init_waitqueue_entry(&ctrl_wait, current); + init_waitqueue_entry(&intr_wait, current); add_wait_queue(sk_sleep(session->ctrl_sock->sk), &ctrl_wait); add_wait_queue(sk_sleep(session->intr_sock->sk), &intr_wait); /* This memory barrier is paired with wq_has_sleeper(). See diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index af68674690af..66e8b6ee19a5 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -57,7 +57,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, u8 ident, u16 dlen, void *data); static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data); -static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size); +static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, @@ -1462,7 +1462,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) set_bit(CONF_REQ_SENT, &chan->conf_state); l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); + l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; } @@ -2966,15 +2966,12 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, return len; } -static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size) +static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) { struct l2cap_conf_opt *opt = *ptr; BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); - if (size < L2CAP_CONF_OPT_SIZE + len) - return; - opt->type = type; opt->len = len; @@ -2999,7 +2996,7 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, s *ptr += L2CAP_CONF_OPT_SIZE + len; } -static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size) +static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) { struct l2cap_conf_efs efs; @@ -3027,7 +3024,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size) } l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), - (unsigned long) &efs, size); + (unsigned long) &efs); } static void l2cap_ack_timeout(struct work_struct *work) @@ -3173,12 +3170,11 @@ static inline void l2cap_txwin_setup(struct l2cap_chan *chan) chan->ack_win = chan->tx_win; } -static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) +static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) { struct l2cap_conf_req *req = data; struct l2cap_conf_rfc rfc = { .mode = chan->mode }; void *ptr = req->data; - void *endptr = data + data_size; u16 size; BT_DBG("chan %p", chan); @@ -3203,7 +3199,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data done: if (chan->imtu != L2CAP_DEFAULT_MTU) - l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr); + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); switch (chan->mode) { case L2CAP_MODE_BASIC: @@ -3222,7 +3218,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data rfc.max_pdu_size = 0; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), - (unsigned long) &rfc, endptr - ptr); + (unsigned long) &rfc); break; case L2CAP_MODE_ERTM: @@ -3242,21 +3238,21 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data L2CAP_DEFAULT_TX_WINDOW); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), - (unsigned long) &rfc, endptr - ptr); + (unsigned long) &rfc); if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) - l2cap_add_opt_efs(&ptr, chan, endptr - ptr); + l2cap_add_opt_efs(&ptr, chan); if (test_bit(FLAG_EXT_CTRL, &chan->flags)) l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, - chan->tx_win, endptr - ptr); + chan->tx_win); if (chan->conn->feat_mask & L2CAP_FEAT_FCS) if (chan->fcs == L2CAP_FCS_NONE || test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { chan->fcs = L2CAP_FCS_NONE; l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, - chan->fcs, endptr - ptr); + chan->fcs); } break; @@ -3274,17 +3270,17 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data rfc.max_pdu_size = cpu_to_le16(size); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), - (unsigned long) &rfc, endptr - ptr); + (unsigned long) &rfc); if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) - l2cap_add_opt_efs(&ptr, chan, endptr - ptr); + l2cap_add_opt_efs(&ptr, chan); if (chan->conn->feat_mask & L2CAP_FEAT_FCS) if (chan->fcs == L2CAP_FCS_NONE || test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { chan->fcs = L2CAP_FCS_NONE; l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, - chan->fcs, endptr - ptr); + chan->fcs); } break; } @@ -3295,11 +3291,10 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data return ptr - data; } -static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) +static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) { struct l2cap_conf_rsp *rsp = data; void *ptr = rsp->data; - void *endptr = data + data_size; void *req = chan->conf_req; int len = chan->conf_len; int type, hint, olen; @@ -3342,10 +3337,9 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data break; case L2CAP_CONF_EFS: - if (olen == sizeof(efs)) { - remote_efs = 1; + remote_efs = 1; + if (olen == sizeof(efs)) memcpy(&efs, (void *) val, olen); - } break; case L2CAP_CONF_EWS: @@ -3402,7 +3396,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data return -ECONNREFUSED; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), - (unsigned long) &rfc, endptr - ptr); + (unsigned long) &rfc); } if (result == L2CAP_CONF_SUCCESS) { @@ -3415,7 +3409,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data chan->omtu = mtu; set_bit(CONF_MTU_DONE, &chan->conf_state); } - l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr); + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); if (remote_efs) { if (chan->local_stype != L2CAP_SERV_NOTRAFIC && @@ -3429,7 +3423,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), - (unsigned long) &efs, endptr - ptr); + (unsigned long) &efs); } else { /* Send PENDING Conf Rsp */ result = L2CAP_CONF_PENDING; @@ -3462,7 +3456,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data set_bit(CONF_MODE_DONE, &chan->conf_state); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, - sizeof(rfc), (unsigned long) &rfc, endptr - ptr); + sizeof(rfc), (unsigned long) &rfc); if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { chan->remote_id = efs.id; @@ -3476,7 +3470,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data le32_to_cpu(efs.sdu_itime); l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), - (unsigned long) &efs, endptr - ptr); + (unsigned long) &efs); } break; @@ -3490,7 +3484,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data set_bit(CONF_MODE_DONE, &chan->conf_state); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), - (unsigned long) &rfc, endptr - ptr); + (unsigned long) &rfc); break; @@ -3512,11 +3506,10 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data } static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, - void *data, size_t size, u16 *result) + void *data, u16 *result) { struct l2cap_conf_req *req = data; void *ptr = req->data; - void *endptr = data + size; int type, olen; unsigned long val; struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; @@ -3534,13 +3527,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, chan->imtu = L2CAP_DEFAULT_MIN_MTU; } else chan->imtu = val; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr); + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); break; case L2CAP_CONF_FLUSH_TO: chan->flush_to = val; l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, - 2, chan->flush_to, endptr - ptr); + 2, chan->flush_to); break; case L2CAP_CONF_RFC: @@ -3554,27 +3547,26 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, chan->fcs = 0; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, - sizeof(rfc), (unsigned long) &rfc, endptr - ptr); + sizeof(rfc), (unsigned long) &rfc); break; case L2CAP_CONF_EWS: chan->ack_win = min_t(u16, val, chan->ack_win); l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, - chan->tx_win, endptr - ptr); + chan->tx_win); break; case L2CAP_CONF_EFS: - if (olen == sizeof(efs)) { + if (olen == sizeof(efs)) memcpy(&efs, (void *)val, olen); - if (chan->local_stype != L2CAP_SERV_NOTRAFIC && - efs.stype != L2CAP_SERV_NOTRAFIC && - efs.stype != chan->local_stype) - return -ECONNREFUSED; + if (chan->local_stype != L2CAP_SERV_NOTRAFIC && + efs.stype != L2CAP_SERV_NOTRAFIC && + efs.stype != chan->local_stype) + return -ECONNREFUSED; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), - (unsigned long) &efs, endptr - ptr); - } + l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), + (unsigned long) &efs); break; case L2CAP_CONF_FCS: @@ -3679,7 +3671,7 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) return; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); + l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; } @@ -3887,7 +3879,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, u8 buf[128]; set_bit(CONF_REQ_SENT, &chan->conf_state); l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); + l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; } @@ -3965,7 +3957,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, break; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(chan, req, sizeof(req)), req); + l2cap_build_conf_req(chan, req), req); chan->num_conf_req++; break; @@ -4077,7 +4069,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, } /* Complete config. */ - len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp)); + len = l2cap_parse_conf_req(chan, rsp); if (len < 0) { l2cap_send_disconn_req(chan, ECONNRESET); goto unlock; @@ -4111,7 +4103,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { u8 buf[64]; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); + l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; } @@ -4171,7 +4163,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, char buf[64]; len = l2cap_parse_conf_rsp(chan, rsp->data, len, - buf, sizeof(buf), &result); + buf, &result); if (len < 0) { l2cap_send_disconn_req(chan, ECONNRESET); goto done; @@ -4201,7 +4193,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, /* throw out any old stored conf requests */ result = L2CAP_CONF_SUCCESS; len = l2cap_parse_conf_rsp(chan, rsp->data, len, - req, sizeof(req), &result); + req, &result); if (len < 0) { l2cap_send_disconn_req(chan, ECONNRESET); goto done; @@ -4778,7 +4770,7 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result, set_bit(CONF_REQ_SENT, &chan->conf_state); l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); + l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; } } @@ -7450,7 +7442,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) set_bit(CONF_REQ_SENT, &chan->conf_state); l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(chan, buf, sizeof(buf)), + l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index d9bbbded49ef..1bb551527044 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -927,7 +927,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (get_user(opt, (u16 __user *) optval)) { + if (get_user(opt, (u32 __user *) optval)) { err = -EFAULT; break; } diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 2209fd2ff2e3..f52bcbf2e58c 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -392,8 +392,7 @@ static void sco_sock_cleanup_listen(struct sock *parent) */ static void sco_sock_kill(struct sock *sk) { - if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket || - sock_flag(sk, SOCK_DEAD)) + if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) return; BT_DBG("sk %p state %d", sk, sk->sk_state); diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 0dc27d2e8f18..4b175df35184 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -525,7 +524,7 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16], if (err) return false; - return !crypto_memneq(bdaddr->b, hash, 3); + return !memcmp(bdaddr->b, hash, 3); } int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa) @@ -578,7 +577,7 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16]) /* This is unlikely, but we need to check that * we didn't accidentially generate a debug key. */ - if (crypto_memneq(smp->local_sk, debug_sk, 32)) + if (memcmp(smp->local_sk, debug_sk, 32)) break; } smp->debug_key = false; @@ -992,7 +991,7 @@ static u8 smp_random(struct smp_chan *smp) if (ret) return SMP_UNSPECIFIED; - if (crypto_memneq(smp->pcnf, confirm, sizeof(smp->pcnf))) { + if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { BT_ERR("Pairing failed (confirmation values mismatch)"); return SMP_CONFIRM_FAILED; } @@ -1492,7 +1491,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) smp->rrnd, r, cfm)) return SMP_UNSPECIFIED; - if (crypto_memneq(smp->pcnf, cfm, 16)) + if (memcmp(smp->pcnf, cfm, 16)) return SMP_CONFIRM_FAILED; smp->passkey_round++; @@ -1876,7 +1875,7 @@ static u8 sc_send_public_key(struct smp_chan *smp) /* This is unlikely, but we need to check that * we didn't accidentially generate a debug key. */ - if (crypto_memneq(smp->local_sk, debug_sk, 32)) + if (memcmp(smp->local_sk, debug_sk, 32)) break; } } @@ -2141,7 +2140,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (crypto_memneq(smp->pcnf, cfm, 16)) + if (memcmp(smp->pcnf, cfm, 16)) return SMP_CONFIRM_FAILED; } else { smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), @@ -2251,14 +2250,8 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) else sec_level = authreq_to_seclevel(auth); - if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK)) { - /* If link is already encrypted with sufficient security we - * still need refresh encryption as per Core Spec 5.0 Vol 3, - * Part H 2.4.6 - */ - smp_ltk_encrypt(conn, hcon->sec_level); + if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK)) return 0; - } if (sec_level > hcon->pending_sec_level) hcon->pending_sec_level = sec_level; @@ -2628,7 +2621,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (crypto_memneq(cfm.confirm_val, smp->pcnf, 16)) + if (memcmp(cfm.confirm_val, smp->pcnf, 16)) return SMP_CONFIRM_FAILED; } @@ -2661,7 +2654,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) else hcon->pending_sec_level = BT_SECURITY_FIPS; - if (!crypto_memneq(debug_pk, smp->remote_pk, 64)) + if (!memcmp(debug_pk, smp->remote_pk, 64)) set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags); if (smp->method == DSP_PASSKEY) { @@ -2760,7 +2753,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (crypto_memneq(check->e, e, 16)) + if (memcmp(check->e, e, 16)) return SMP_DHKEY_CHECK_FAILED; if (!hcon->out) { @@ -3470,7 +3463,7 @@ static int __init test_ah(struct crypto_blkcipher *tfm_aes) if (err) return err; - if (crypto_memneq(res, exp, 3)) + if (memcmp(res, exp, 3)) return -EINVAL; return 0; @@ -3500,7 +3493,7 @@ static int __init test_c1(struct crypto_blkcipher *tfm_aes) if (err) return err; - if (crypto_memneq(res, exp, 16)) + if (memcmp(res, exp, 16)) return -EINVAL; return 0; @@ -3525,7 +3518,7 @@ static int __init test_s1(struct crypto_blkcipher *tfm_aes) if (err) return err; - if (crypto_memneq(res, exp, 16)) + if (memcmp(res, exp, 16)) return -EINVAL; return 0; @@ -3557,7 +3550,7 @@ static int __init test_f4(struct crypto_hash *tfm_cmac) if (err) return err; - if (crypto_memneq(res, exp, 16)) + if (memcmp(res, exp, 16)) return -EINVAL; return 0; @@ -3591,10 +3584,10 @@ static int __init test_f5(struct crypto_hash *tfm_cmac) if (err) return err; - if (crypto_memneq(mackey, exp_mackey, 16)) + if (memcmp(mackey, exp_mackey, 16)) return -EINVAL; - if (crypto_memneq(ltk, exp_ltk, 16)) + if (memcmp(ltk, exp_ltk, 16)) return -EINVAL; return 0; @@ -3627,7 +3620,7 @@ static int __init test_f6(struct crypto_hash *tfm_cmac) if (err) return err; - if (crypto_memneq(res, exp, 16)) + if (memcmp(res, exp, 16)) return -EINVAL; return 0; @@ -3681,7 +3674,7 @@ static int __init test_h6(struct crypto_hash *tfm_cmac) if (err) return err; - if (crypto_memneq(res, exp, 16)) + if (memcmp(res, exp, 16)) return -EINVAL; return 0; diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 09442e0f7f67..a642bb829d09 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -278,8 +278,6 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr) * change from under us. */ list_for_each_entry(v, &vg->vlan_list, vlist) { - if (!br_vlan_should_use(v)) - continue; f = __br_fdb_get(br, br->dev->dev_addr, v->vid); if (f && f->is_local && !f->dst) fdb_delete_local(br, NULL, f); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 50e84e634dfe..ec02f5869a78 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -456,8 +456,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) return -ELOOP; - /* Device has master upper dev */ - if (netdev_master_upper_dev_get(dev)) + /* Device is already being bridged */ + if (br_port_exists(dev)) return -EBUSY; /* No bridging devices that dislike that (e.g. wireless) */ @@ -511,11 +511,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (br_fdb_insert(br, p, dev->dev_addr, 0)) netdev_err(dev, "failed insert local address bridge forwarding table\n"); - err = nbp_vlan_init(p); - if (err) { + if (nbp_vlan_init(p)) netdev_err(dev, "failed to initialize vlan filtering on this port\n"); - goto err6; - } spin_lock_bh(&br->lock); changed_addr = br_stp_recalculate_bridge_id(br); @@ -536,12 +533,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) return 0; -err6: - list_del_rcu(&p->list); - br_fdb_delete_by_port(br, p, 0, 1); - nbp_update_port_count(br); - netdev_upper_dev_unlink(dev, br->dev); - err5: dev->priv_flags &= ~IFF_BRIDGE_PORT; netdev_rx_handler_unregister(dev); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index e24754a0e052..f7fba74108a9 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -29,7 +29,6 @@ EXPORT_SYMBOL(br_should_route_hook); static int br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb) { - br_drop_fake_rtable(skb); return netif_receive_skb(skb); } diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index d80c15d028fe..ea9893743a0f 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -464,11 +464,8 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0, &ip6h->saddr)) { kfree_skb(skb); - br->has_ipv6_addr = 0; return NULL; } - - br->has_ipv6_addr = 1; ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); hopopt = (u8 *)(ip6h + 1); @@ -951,12 +948,13 @@ static void br_multicast_enable(struct bridge_mcast_own_query *query) mod_timer(&query->timer, jiffies); } -static void __br_multicast_enable_port(struct net_bridge_port *port) +void br_multicast_enable_port(struct net_bridge_port *port) { struct net_bridge *br = port->br; + spin_lock(&br->multicast_lock); if (br->multicast_disabled || !netif_running(br->dev)) - return; + goto out; br_multicast_enable(&port->ip4_own_query); #if IS_ENABLED(CONFIG_IPV6) @@ -964,14 +962,8 @@ static void __br_multicast_enable_port(struct net_bridge_port *port) #endif if (port->multicast_router == 2 && hlist_unhashed(&port->rlist)) br_multicast_add_router(br, port); -} - -void br_multicast_enable_port(struct net_bridge_port *port) -{ - struct net_bridge *br = port->br; - spin_lock(&br->multicast_lock); - __br_multicast_enable_port(port); +out: spin_unlock(&br->multicast_lock); } @@ -1118,7 +1110,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, } else { err = br_ip6_multicast_add_group(br, port, &grec->grec_mca, vid); - if (err) + if (!err) break; } } @@ -1744,7 +1736,6 @@ void br_multicast_init(struct net_bridge *br) br->ip6_other_query.delay_time = 0; br->ip6_querier.port = NULL; #endif - br->has_ipv6_addr = 1; spin_lock_init(&br->multicast_lock); setup_timer(&br->multicast_router_timer, @@ -1910,9 +1901,8 @@ static void br_multicast_start_querier(struct net_bridge *br, int br_multicast_toggle(struct net_bridge *br, unsigned long val) { - struct net_bridge_mdb_htable *mdb; - struct net_bridge_port *port; int err = 0; + struct net_bridge_mdb_htable *mdb; spin_lock_bh(&br->multicast_lock); if (br->multicast_disabled == !val) @@ -1940,9 +1930,10 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val) goto rollback; } - br_multicast_open(br); - list_for_each_entry(port, &br->port_list, list) - __br_multicast_enable_port(port); + br_multicast_start_querier(br, &br->ip4_own_query); +#if IS_ENABLED(CONFIG_IPV6) + br_multicast_start_querier(br, &br->ip6_own_query); +#endif unlock: spin_unlock_bh(&br->multicast_lock); diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index 55dcb2b20b59..7ddbe7ec81d6 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -516,6 +516,21 @@ static unsigned int br_nf_pre_routing(void *priv, } +/* PF_BRIDGE/LOCAL_IN ************************************************/ +/* The packet is locally destined, which requires a real + * dst_entry, so detach the fake one. On the way up, the + * packet would pass through PRE_ROUTING again (which already + * took place when the packet entered the bridge), but we + * register an IPv4 PRE_ROUTING 'sabotage' hook that will + * prevent this from happening. */ +static unsigned int br_nf_local_in(void *priv, + struct sk_buff *skb, + const struct nf_hook_state *state) +{ + br_drop_fake_rtable(skb); + return NF_ACCEPT; +} + /* PF_BRIDGE/FORWARD *************************************************/ static int br_nf_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { @@ -701,20 +716,18 @@ static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) { - struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); - unsigned int mtu, mtu_reserved; + struct nf_bridge_info *nf_bridge; + unsigned int mtu_reserved; mtu_reserved = nf_bridge_mtu_reduction(skb); - mtu = skb->dev->mtu; - if (nf_bridge->frag_max_size && nf_bridge->frag_max_size < mtu) - mtu = nf_bridge->frag_max_size; - - if (skb_is_gso(skb) || skb->len + mtu_reserved <= mtu) { + if (skb_is_gso(skb) || skb->len + mtu_reserved <= skb->dev->mtu) { nf_bridge_info_free(skb); return br_dev_queue_push_xmit(net, sk, skb); } + nf_bridge = nf_bridge_info_get(skb); + /* This is wrong! We should preserve the original fragment * boundaries by preserving frag_list rather than refragmenting. */ @@ -887,6 +900,12 @@ static struct nf_hook_ops br_nf_ops[] __read_mostly = { .hooknum = NF_BR_PRE_ROUTING, .priority = NF_BR_PRI_BRNF, }, + { + .hook = br_nf_local_in, + .pf = NFPROTO_BRIDGE, + .hooknum = NF_BR_LOCAL_IN, + .priority = NF_BR_PRI_BRNF, + }, { .hook = br_nf_forward_ip, .pf = NFPROTO_BRIDGE, diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 0ce26a0f7913..40197ff8918a 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -768,16 +768,23 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[]) return -EPROTONOSUPPORT; } } +#endif - if (data[IFLA_BR_VLAN_DEFAULT_PVID]) { - __u16 defpvid = nla_get_u16(data[IFLA_BR_VLAN_DEFAULT_PVID]); + return 0; +} - if (defpvid >= VLAN_VID_MASK) - return -EINVAL; +static int br_dev_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +{ + struct net_bridge *br = netdev_priv(dev); + + if (tb[IFLA_ADDRESS]) { + spin_lock_bh(&br->lock); + br_stp_change_bridge_id(br, nla_data(tb[IFLA_ADDRESS])); + spin_unlock_bh(&br->lock); } -#endif - return 0; + return register_netdevice(dev); } static int br_port_slave_changelink(struct net_device *brdev, @@ -1061,29 +1068,6 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], return 0; } -static int br_dev_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[]) -{ - struct net_bridge *br = netdev_priv(dev); - int err; - - err = register_netdevice(dev); - if (err) - return err; - - if (tb[IFLA_ADDRESS]) { - spin_lock_bh(&br->lock); - br_stp_change_bridge_id(br, nla_data(tb[IFLA_ADDRESS])); - spin_unlock_bh(&br->lock); - } - - err = br_changelink(dev, tb, data); - if (err) - br_dev_delete(dev, NULL); - - return err; -} - static size_t br_get_size(const struct net_device *brdev) { return nla_total_size(sizeof(u32)) + /* IFLA_BR_FORWARD_DELAY */ diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1001a1b7df9b..216018c76018 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -301,7 +301,6 @@ struct net_bridge u8 multicast_disabled:1; u8 multicast_querier:1; u8 multicast_query_use_ifaddr:1; - u8 has_ipv6_addr:1; u32 hash_elasticity; u32 hash_max; @@ -575,22 +574,10 @@ static inline bool br_multicast_is_router(struct net_bridge *br) static inline bool __br_multicast_querier_exists(struct net_bridge *br, - struct bridge_mcast_other_query *querier, - const bool is_ipv6) + struct bridge_mcast_other_query *querier) { - bool own_querier_enabled; - - if (br->multicast_querier) { - if (is_ipv6 && !br->has_ipv6_addr) - own_querier_enabled = false; - else - own_querier_enabled = true; - } else { - own_querier_enabled = false; - } - return time_is_before_jiffies(querier->delay_time) && - (own_querier_enabled || timer_pending(&querier->timer)); + (br->multicast_querier || timer_pending(&querier->timer)); } static inline bool br_multicast_querier_exists(struct net_bridge *br, @@ -598,12 +585,10 @@ static inline bool br_multicast_querier_exists(struct net_bridge *br, { switch (eth->h_proto) { case (htons(ETH_P_IP)): - return __br_multicast_querier_exists(br, - &br->ip4_other_query, false); + return __br_multicast_querier_exists(br, &br->ip4_other_query); #if IS_ENABLED(CONFIG_IPV6) case (htons(ETH_P_IPV6)): - return __br_multicast_querier_exists(br, - &br->ip6_other_query, true); + return __br_multicast_querier_exists(br, &br->ip6_other_query); #endif default: return false; diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index bcb4559e735d..8a7ada8bb947 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -166,8 +166,6 @@ static void br_stp_start(struct net_bridge *br) br_debug(br, "using kernel STP\n"); /* To start timers on any ports left in blocking */ - if (br->dev->flags & IFF_UP) - mod_timer(&br->hello_timer, jiffies + br->hello_time); br_port_state_selection(br); } diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 7dbe6a5c31eb..5f0f5af0ec35 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c @@ -40,7 +40,7 @@ static void br_hello_timer_expired(unsigned long arg) if (br->dev->flags & IFF_UP) { br_config_bpdu_generation(br); - if (br->stp_enabled == BR_KERNEL_STP) + if (br->stp_enabled != BR_USER_STP) mod_timer(&br->hello_timer, round_jiffies(jiffies + br->hello_time)); } diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 83bb695f9645..efe415ad842a 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -229,9 +229,6 @@ static ssize_t brport_show(struct kobject *kobj, struct brport_attribute *brport_attr = to_brport_attr(attr); struct net_bridge_port *p = to_brport(kobj); - if (!brport_attr->show) - return -EINVAL; - return brport_attr->show(p, buf); } diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c index 9adf16258cab..9024283d2bca 100644 --- a/net/bridge/netfilter/ebt_among.c +++ b/net/bridge/netfilter/ebt_among.c @@ -172,69 +172,18 @@ ebt_among_mt(const struct sk_buff *skb, struct xt_action_param *par) return true; } -static bool poolsize_invalid(const struct ebt_mac_wormhash *w) -{ - return w && w->poolsize >= (INT_MAX / sizeof(struct ebt_mac_wormhash_tuple)); -} - -static bool wormhash_offset_invalid(int off, unsigned int len) -{ - if (off == 0) /* not present */ - return false; - - if (off < (int)sizeof(struct ebt_among_info) || - off % __alignof__(struct ebt_mac_wormhash)) - return true; - - off += sizeof(struct ebt_mac_wormhash); - - return off > len; -} - -static bool wormhash_sizes_valid(const struct ebt_mac_wormhash *wh, int a, int b) -{ - if (a == 0) - a = sizeof(struct ebt_among_info); - - return ebt_mac_wormhash_size(wh) + a == b; -} - static int ebt_among_mt_check(const struct xt_mtchk_param *par) { const struct ebt_among_info *info = par->matchinfo; const struct ebt_entry_match *em = container_of(par->matchinfo, const struct ebt_entry_match, data); - unsigned int expected_length = sizeof(struct ebt_among_info); + int expected_length = sizeof(struct ebt_among_info); const struct ebt_mac_wormhash *wh_dst, *wh_src; int err; - if (expected_length > em->match_size) - return -EINVAL; - - if (wormhash_offset_invalid(info->wh_dst_ofs, em->match_size) || - wormhash_offset_invalid(info->wh_src_ofs, em->match_size)) - return -EINVAL; - wh_dst = ebt_among_wh_dst(info); - if (poolsize_invalid(wh_dst)) - return -EINVAL; - - expected_length += ebt_mac_wormhash_size(wh_dst); - if (expected_length > em->match_size) - return -EINVAL; - wh_src = ebt_among_wh_src(info); - if (poolsize_invalid(wh_src)) - return -EINVAL; - - if (info->wh_src_ofs < info->wh_dst_ofs) { - if (!wormhash_sizes_valid(wh_src, info->wh_src_ofs, info->wh_dst_ofs)) - return -EINVAL; - } else { - if (!wormhash_sizes_valid(wh_dst, info->wh_dst_ofs, info->wh_src_ofs)) - return -EINVAL; - } - + expected_length += ebt_mac_wormhash_size(wh_dst); expected_length += ebt_mac_wormhash_size(wh_src); if (em->match_size != EBT_ALIGN(expected_length)) { diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 8b8a43fda6ca..f46ca417bf2d 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -404,12 +404,6 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par, watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0); if (IS_ERR(watcher)) return PTR_ERR(watcher); - - if (watcher->family != NFPROTO_BRIDGE) { - module_put(watcher->me); - return -ENOENT; - } - w->u.watcher = watcher; par->target = watcher; @@ -707,8 +701,6 @@ ebt_check_entry(struct ebt_entry *e, struct net *net, } i = 0; - memset(&mtpar, 0, sizeof(mtpar)); - memset(&tgpar, 0, sizeof(tgpar)); mtpar.net = tgpar.net = net; mtpar.table = tgpar.table = name; mtpar.entryinfo = tgpar.entryinfo = e; @@ -730,13 +722,6 @@ ebt_check_entry(struct ebt_entry *e, struct net *net, goto cleanup_watchers; } - /* Reject UNSPEC, xtables verdicts/return values are incompatible */ - if (target->family != NFPROTO_BRIDGE) { - module_put(target->me); - ret = -ENOENT; - goto cleanup_watchers; - } - t->u.target = target; if (t->u.target == &ebt_standard_target) { if (gap < sizeof(struct ebt_standard_target)) { @@ -1629,8 +1614,7 @@ static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr, int off = ebt_compat_match_offset(match, m->match_size); compat_uint_t msize = m->match_size - off; - if (WARN_ON(off >= m->match_size)) - return -EINVAL; + BUG_ON(off >= m->match_size); if (copy_to_user(cm->u.name, match->name, strlen(match->name) + 1) || put_user(msize, &cm->match_size)) @@ -1657,8 +1641,7 @@ static int compat_target_to_user(struct ebt_entry_target *t, int off = xt_compat_target_offset(target); compat_uint_t tsize = t->target_size - off; - if (WARN_ON(off >= t->target_size)) - return -EINVAL; + BUG_ON(off >= t->target_size); if (copy_to_user(cm->u.name, target->name, strlen(target->name) + 1) || put_user(tsize, &cm->match_size)) @@ -1886,8 +1869,7 @@ static int ebt_buf_add(struct ebt_entries_buf_state *state, if (state->buf_kern_start == NULL) goto count_only; - if (WARN_ON(state->buf_kern_offset + sz > state->buf_kern_len)) - return -EINVAL; + BUG_ON(state->buf_kern_offset + sz > state->buf_kern_len); memcpy(state->buf_kern_start + state->buf_kern_offset, data, sz); @@ -1900,8 +1882,7 @@ static int ebt_buf_add_pad(struct ebt_entries_buf_state *state, unsigned int sz) { char *b = state->buf_kern_start; - if (WARN_ON(b && state->buf_kern_offset > state->buf_kern_len)) - return -EINVAL; + BUG_ON(b && state->buf_kern_offset > state->buf_kern_len); if (b != NULL && sz > 0) memset(b + state->buf_kern_offset, 0, sz); @@ -1927,8 +1908,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, int off, pad = 0; unsigned int size_kern, match_size = mwt->match_size; - if (strscpy(name, mwt->u.name, sizeof(name)) < 0) - return -EINVAL; + strlcpy(name, mwt->u.name, sizeof(name)); if (state->buf_kern_start) dst = state->buf_kern_start + state->buf_kern_offset; @@ -1979,10 +1959,8 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, pad = XT_ALIGN(size_kern) - size_kern; if (pad > 0 && dst) { - if (WARN_ON(state->buf_kern_len <= pad)) - return -EINVAL; - if (WARN_ON(state->buf_kern_offset - (match_size + off) + size_kern > state->buf_kern_len - pad)) - return -EINVAL; + BUG_ON(state->buf_kern_len <= pad); + BUG_ON(state->buf_kern_offset - (match_size + off) + size_kern > state->buf_kern_len - pad); memset(dst + size_kern, 0, pad); } return off + match_size; @@ -2033,8 +2011,7 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, if (ret < 0) return ret; - if (WARN_ON(ret < match32->match_size)) - return -EINVAL; + BUG_ON(ret < match32->match_size); growth += ret - match32->match_size; growth += ebt_compat_entry_padsize(); @@ -2044,9 +2021,7 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, if (match_kern) match_kern->match_size = ret; - if (WARN_ON(type == EBT_COMPAT_TARGET && size_left)) - return -EINVAL; - + WARN_ON(type == EBT_COMPAT_TARGET && size_left); match32 = (struct compat_ebt_entry_mwt *) buf; } @@ -2103,19 +2078,6 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, * * offsets are relative to beginning of struct ebt_entry (i.e., 0). */ - for (i = 0; i < 4 ; ++i) { - if (offsets[i] > *total) - return -EINVAL; - - if (i < 3 && offsets[i] == *total) - return -EINVAL; - - if (i == 0) - continue; - if (offsets[i-1] > offsets[i]) - return -EINVAL; - } - for (i = 0, j = 1 ; j < 4 ; j++, i++) { struct compat_ebt_entry_mwt *match32; unsigned int size; @@ -2148,8 +2110,7 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, startoff = state->buf_user_offset - startoff; - if (WARN_ON(*total < startoff)) - return -EINVAL; + BUG_ON(*total < startoff); *total -= startoff; return 0; } @@ -2277,8 +2238,7 @@ static int compat_do_replace(struct net *net, void __user *user, state.buf_kern_len = size64; ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); - if (WARN_ON(ret < 0)) - goto out_unlock; + BUG_ON(ret < 0); /* parses same data again */ vfree(entries_tmp); tmp.entries_size = size64; diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index a0443d40d677..d730a0f68f46 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -131,10 +131,8 @@ static void caif_flow_cb(struct sk_buff *skb) caifd = caif_get(skb->dev); WARN_ON(caifd == NULL); - if (!caifd) { - rcu_read_unlock(); + if (caifd == NULL) return; - } caifd_hold(caifd); rcu_read_unlock(); diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index 71b6ab240dea..f6c3b2137eea 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c @@ -81,7 +81,11 @@ static struct cfpkt *cfpkt_create_pfx(u16 len, u16 pfx) { struct sk_buff *skb; - skb = alloc_skb(len + pfx, GFP_ATOMIC); + if (likely(in_interrupt())) + skb = alloc_skb(len + pfx, GFP_ATOMIC); + else + skb = alloc_skb(len + pfx, GFP_KERNEL); + if (unlikely(skb == NULL)) return NULL; @@ -282,7 +286,7 @@ int cfpkt_setlen(struct cfpkt *pkt, u16 len) else skb_trim(skb, len); - return cfpkt_getlen(pkt); + return cfpkt_getlen(pkt); } /* Need to expand SKB */ diff --git a/net/can/af_can.c b/net/can/af_can.c index c866e761651a..166d436196c1 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -445,7 +445,6 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, * @func: callback function on filter match * @data: returned parameter for callback function * @ident: string for calling module identification - * @sk: socket pointer (might be NULL) * * Description: * Invokes the callback function with the received sk_buff and the given @@ -469,7 +468,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, */ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, void (*func)(struct sk_buff *, void *), void *data, - char *ident, struct sock *sk) + char *ident) { struct receiver *r; struct hlist_head *rl; @@ -497,7 +496,6 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, r->func = func; r->data = data; r->ident = ident; - r->sk = sk; hlist_add_head_rcu(&r->list, rl); d->entries++; @@ -522,11 +520,8 @@ EXPORT_SYMBOL(can_rx_register); static void can_rx_delete_receiver(struct rcu_head *rp) { struct receiver *r = container_of(rp, struct receiver, rcu); - struct sock *sk = r->sk; kmem_cache_free(rcv_cache, r); - if (sk) - sock_put(sk); } /** @@ -601,11 +596,8 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, spin_unlock(&can_rcvlists_lock); /* schedule the receiver item for deletion */ - if (r) { - if (r->sk) - sock_hold(r->sk); + if (r) call_rcu(&r->rcu, can_rx_delete_receiver); - } } EXPORT_SYMBOL(can_rx_unregister); @@ -722,12 +714,13 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, if (unlikely(!net_eq(dev_net(dev), &init_net))) goto drop; - if (unlikely(dev->type != ARPHRD_CAN || skb->len != CAN_MTU || - cfd->len > CAN_MAX_DLEN)) { - pr_warn_once("PF_CAN: dropped non conform CAN skbuf: dev type %d, len %d, datalen %d\n", - dev->type, skb->len, cfd->len); + if (WARN_ONCE(dev->type != ARPHRD_CAN || + skb->len != CAN_MTU || + cfd->len > CAN_MAX_DLEN, + "PF_CAN: dropped non conform CAN skbuf: " + "dev type %d, len %d, datalen %d\n", + dev->type, skb->len, cfd->len)) goto drop; - } can_receive(skb, dev); return NET_RX_SUCCESS; @@ -745,12 +738,13 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, if (unlikely(!net_eq(dev_net(dev), &init_net))) goto drop; - if (unlikely(dev->type != ARPHRD_CAN || skb->len != CANFD_MTU || - cfd->len > CANFD_MAX_DLEN)) { - pr_warn_once("PF_CAN: dropped non conform CAN FD skbuf: dev type %d, len %d, datalen %d\n", - dev->type, skb->len, cfd->len); + if (WARN_ONCE(dev->type != ARPHRD_CAN || + skb->len != CANFD_MTU || + cfd->len > CANFD_MAX_DLEN, + "PF_CAN: dropped non conform CAN FD skbuf: " + "dev type %d, len %d, datalen %d\n", + dev->type, skb->len, cfd->len)) goto drop; - } can_receive(skb, dev); return NET_RX_SUCCESS; diff --git a/net/can/af_can.h b/net/can/af_can.h index b86f5129e838..fca0fe9fc45a 100644 --- a/net/can/af_can.h +++ b/net/can/af_can.h @@ -50,14 +50,13 @@ struct receiver { struct hlist_node list; + struct rcu_head rcu; canid_t can_id; canid_t mask; unsigned long matches; void (*func)(struct sk_buff *, void *); void *data; char *ident; - struct sock *sk; - struct rcu_head rcu; }; #define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS) diff --git a/net/can/bcm.c b/net/can/bcm.c index 4ccfd356baed..6863310d6973 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -710,23 +710,14 @@ static struct bcm_op *bcm_find_op(struct list_head *ops, canid_t can_id, static void bcm_remove_op(struct bcm_op *op) { - if (op->tsklet.func) { - while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) || - test_bit(TASKLET_STATE_RUN, &op->tsklet.state) || - hrtimer_active(&op->timer)) { - hrtimer_cancel(&op->timer); - tasklet_kill(&op->tsklet); - } - } + hrtimer_cancel(&op->timer); + hrtimer_cancel(&op->thrtimer); - if (op->thrtsklet.func) { - while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) || - test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) || - hrtimer_active(&op->thrtimer)) { - hrtimer_cancel(&op->thrtimer); - tasklet_kill(&op->thrtsklet); - } - } + if (op->tsklet.func) + tasklet_kill(&op->tsklet); + + if (op->thrtsklet.func) + tasklet_kill(&op->thrtsklet); if ((op->frames) && (op->frames != &op->sframe)) kfree(op->frames); @@ -1179,7 +1170,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, err = can_rx_register(dev, op->can_id, REGMASK(op->can_id), bcm_rx_handler, op, - "bcm", sk); + "bcm"); op->rx_reg_dev = dev; dev_put(dev); @@ -1188,7 +1179,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, } else err = can_rx_register(NULL, op->can_id, REGMASK(op->can_id), - bcm_rx_handler, op, "bcm", sk); + bcm_rx_handler, op, "bcm"); if (err) { /* this bcm rx op is broken -> remove it */ list_del(&op->list); @@ -1509,31 +1500,24 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len, struct sockaddr_can *addr = (struct sockaddr_can *)uaddr; struct sock *sk = sock->sk; struct bcm_sock *bo = bcm_sk(sk); - int ret = 0; if (len < sizeof(*addr)) return -EINVAL; - lock_sock(sk); - - if (bo->bound) { - ret = -EISCONN; - goto fail; - } + if (bo->bound) + return -EISCONN; /* bind a device to this socket */ if (addr->can_ifindex) { struct net_device *dev; dev = dev_get_by_index(&init_net, addr->can_ifindex); - if (!dev) { - ret = -ENODEV; - goto fail; - } + if (!dev) + return -ENODEV; + if (dev->type != ARPHRD_CAN) { dev_put(dev); - ret = -ENODEV; - goto fail; + return -ENODEV; } bo->ifindex = dev->ifindex; @@ -1544,24 +1528,17 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len, bo->ifindex = 0; } + bo->bound = 1; + if (proc_dir) { /* unique socket address as filename */ sprintf(bo->procname, "%lu", sock_i_ino(sk)); bo->bcm_proc_read = proc_create_data(bo->procname, 0644, proc_dir, &bcm_proc_fops, sk); - if (!bo->bcm_proc_read) { - ret = -ENOMEM; - goto fail; - } } - bo->bound = 1; - -fail: - release_sock(sk); - - return ret; + return 0; } static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, diff --git a/net/can/gw.c b/net/can/gw.c index 77c8af4047ef..455168718c2e 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -442,7 +442,7 @@ static inline int cgw_register_filter(struct cgw_job *gwj) { return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id, gwj->ccgw.filter.can_mask, can_can_gw_rcv, - gwj, "gw", NULL); + gwj, "gw"); } static inline void cgw_unregister_filter(struct cgw_job *gwj) diff --git a/net/can/raw.c b/net/can/raw.c index e9403a26a1d5..2e67b1423cd3 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -190,7 +190,7 @@ static int raw_enable_filters(struct net_device *dev, struct sock *sk, for (i = 0; i < count; i++) { err = can_rx_register(dev, filter[i].can_id, filter[i].can_mask, - raw_rcv, sk, "raw", sk); + raw_rcv, sk, "raw"); if (err) { /* clean up successfully registered filters */ while (--i >= 0) @@ -211,7 +211,7 @@ static int raw_enable_errfilter(struct net_device *dev, struct sock *sk, if (err_mask) err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG, - raw_rcv, sk, "raw", sk); + raw_rcv, sk, "raw"); return err; } @@ -499,9 +499,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, if (optlen % sizeof(struct can_filter) != 0) return -EINVAL; - if (optlen > CAN_RAW_FILTER_MAX * sizeof(struct can_filter)) - return -EINVAL; - count = optlen / sizeof(struct can_filter); if (count > 1) { diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index ad3c9e96a275..63ae5dd24fc5 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -479,16 +478,11 @@ static int ceph_tcp_connect(struct ceph_connection *con) { struct sockaddr_storage *paddr = &con->peer_addr.in_addr; struct socket *sock; - unsigned int noio_flag; int ret; BUG_ON(con->sock); - - /* sock_create_kern() allocates with GFP_KERNEL */ - noio_flag = memalloc_noio_save(); ret = sock_create_kern(read_pnet(&con->msgr->net), paddr->ss_family, SOCK_STREAM, IPPROTO_TCP, &sock); - memalloc_noio_restore(noio_flag); if (ret) return ret; sock->sk->sk_allocation = GFP_NOFS; @@ -2048,19 +2042,6 @@ static int process_connect(struct ceph_connection *con) dout("process_connect on %p tag %d\n", con, (int)con->in_tag); - if (con->auth_reply_buf) { - /* - * Any connection that defines ->get_authorizer() - * should also define ->verify_authorizer_reply(). - * See get_connect_authorizer(). - */ - ret = con->ops->verify_authorizer_reply(con, 0); - if (ret < 0) { - con->error_msg = "bad authorize reply"; - return ret; - } - } - switch (con->in_reply.tag) { case CEPH_MSGR_TAG_FEATURES: pr_err("%s%lld %s feature set mismatch," @@ -2531,11 +2512,6 @@ static int try_write(struct ceph_connection *con) int ret = 1; dout("try_write start %p state %lu\n", con, con->state); - if (con->state != CON_STATE_PREOPEN && - con->state != CON_STATE_CONNECTING && - con->state != CON_STATE_NEGOTIATING && - con->state != CON_STATE_OPEN) - return 0; more: dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes); @@ -2561,8 +2537,6 @@ static int try_write(struct ceph_connection *con) } more_kvec: - BUG_ON(!con->sock); - /* kvec data queued? */ if (con->out_kvec_left) { ret = write_partial_kvec(con); diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 378c9ed00d40..7d8f581d9f1f 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -295,7 +295,6 @@ static struct crush_map *crush_decode(void *pbyval, void *end) u32 yes; struct crush_rule *r; - err = -EINVAL; ceph_decode_32_safe(p, end, yes, bad); if (!yes) { dout("crush_decode NO rule %d off %x %p to %p\n", @@ -1192,114 +1191,6 @@ struct ceph_osdmap *ceph_osdmap_decode(void **p, void *end) return map; } -/* - * Encoding order is (new_up_client, new_state, new_weight). Need to - * apply in the (new_weight, new_state, new_up_client) order, because - * an incremental map may look like e.g. - * - * new_up_client: { osd=6, addr=... } # set osd_state and addr - * new_state: { osd=6, xorstate=EXISTS } # clear osd_state - */ -static int decode_new_up_state_weight(void **p, void *end, - struct ceph_osdmap *map) -{ - void *new_up_client; - void *new_state; - void *new_weight_end; - u32 len; - - new_up_client = *p; - ceph_decode_32_safe(p, end, len, e_inval); - len *= sizeof(u32) + sizeof(struct ceph_entity_addr); - ceph_decode_need(p, end, len, e_inval); - *p += len; - - new_state = *p; - ceph_decode_32_safe(p, end, len, e_inval); - len *= sizeof(u32) + sizeof(u8); - ceph_decode_need(p, end, len, e_inval); - *p += len; - - /* new_weight */ - ceph_decode_32_safe(p, end, len, e_inval); - while (len--) { - s32 osd; - u32 w; - - ceph_decode_need(p, end, 2*sizeof(u32), e_inval); - osd = ceph_decode_32(p); - w = ceph_decode_32(p); - BUG_ON(osd >= map->max_osd); - pr_info("osd%d weight 0x%x %s\n", osd, w, - w == CEPH_OSD_IN ? "(in)" : - (w == CEPH_OSD_OUT ? "(out)" : "")); - map->osd_weight[osd] = w; - - /* - * If we are marking in, set the EXISTS, and clear the - * AUTOOUT and NEW bits. - */ - if (w) { - map->osd_state[osd] |= CEPH_OSD_EXISTS; - map->osd_state[osd] &= ~(CEPH_OSD_AUTOOUT | - CEPH_OSD_NEW); - } - } - new_weight_end = *p; - - /* new_state (up/down) */ - *p = new_state; - len = ceph_decode_32(p); - while (len--) { - s32 osd; - u8 xorstate; - int ret; - - osd = ceph_decode_32(p); - xorstate = ceph_decode_8(p); - if (xorstate == 0) - xorstate = CEPH_OSD_UP; - BUG_ON(osd >= map->max_osd); - if ((map->osd_state[osd] & CEPH_OSD_UP) && - (xorstate & CEPH_OSD_UP)) - pr_info("osd%d down\n", osd); - if ((map->osd_state[osd] & CEPH_OSD_EXISTS) && - (xorstate & CEPH_OSD_EXISTS)) { - pr_info("osd%d does not exist\n", osd); - ret = set_primary_affinity(map, osd, - CEPH_OSD_DEFAULT_PRIMARY_AFFINITY); - if (ret) - return ret; - memset(map->osd_addr + osd, 0, sizeof(*map->osd_addr)); - map->osd_state[osd] = 0; - } else { - map->osd_state[osd] ^= xorstate; - } - } - - /* new_up_client */ - *p = new_up_client; - len = ceph_decode_32(p); - while (len--) { - s32 osd; - struct ceph_entity_addr addr; - - osd = ceph_decode_32(p); - ceph_decode_copy(p, &addr, sizeof(addr)); - ceph_decode_addr(&addr); - BUG_ON(osd >= map->max_osd); - pr_info("osd%d up\n", osd); - map->osd_state[osd] |= CEPH_OSD_EXISTS | CEPH_OSD_UP; - map->osd_addr[osd] = addr; - } - - *p = new_weight_end; - return 0; - -e_inval: - return -EINVAL; -} - /* * decode and apply an incremental map update. */ @@ -1399,10 +1290,49 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, __remove_pg_pool(&map->pg_pools, pi); } - /* new_up_client, new_state, new_weight */ - err = decode_new_up_state_weight(p, end, map); - if (err) - goto bad; + /* new_up */ + ceph_decode_32_safe(p, end, len, e_inval); + while (len--) { + u32 osd; + struct ceph_entity_addr addr; + ceph_decode_32_safe(p, end, osd, e_inval); + ceph_decode_copy_safe(p, end, &addr, sizeof(addr), e_inval); + ceph_decode_addr(&addr); + pr_info("osd%d up\n", osd); + BUG_ON(osd >= map->max_osd); + map->osd_state[osd] |= CEPH_OSD_UP | CEPH_OSD_EXISTS; + map->osd_addr[osd] = addr; + } + + /* new_state */ + ceph_decode_32_safe(p, end, len, e_inval); + while (len--) { + u32 osd; + u8 xorstate; + ceph_decode_32_safe(p, end, osd, e_inval); + xorstate = **(u8 **)p; + (*p)++; /* clean flag */ + if (xorstate == 0) + xorstate = CEPH_OSD_UP; + if (xorstate & CEPH_OSD_UP) + pr_info("osd%d down\n", osd); + if (osd < map->max_osd) + map->osd_state[osd] ^= xorstate; + } + + /* new_weight */ + ceph_decode_32_safe(p, end, len, e_inval); + while (len--) { + u32 osd, off; + ceph_decode_need(p, end, sizeof(u32)*2, e_inval); + osd = ceph_decode_32(p); + off = ceph_decode_32(p); + pr_info("osd%d weight 0x%x %s\n", osd, off, + off == CEPH_OSD_IN ? "(in)" : + (off == CEPH_OSD_OUT ? "(out)" : "")); + if (osd < map->max_osd) + map->osd_weight[osd] = off; + } /* new_pg_temp */ err = decode_new_pg_temp(p, end, map); diff --git a/net/compat.c b/net/compat.c index 17e97b106458..5cfd26a0006f 100644 --- a/net/compat.c +++ b/net/compat.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -358,8 +357,7 @@ static int compat_sock_setsockopt(struct socket *sock, int level, int optname, if (optname == SO_ATTACH_FILTER) return do_set_attach_filter(sock, level, optname, optval, optlen); - if (!COMPAT_USE_64BIT_TIME && - (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) + if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) return do_set_sock_timeout(sock, level, optname, optval, optlen); return sock_setsockopt(sock, level, optname, optval, optlen); @@ -424,8 +422,7 @@ static int do_get_sock_timeout(struct socket *sock, int level, int optname, static int compat_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { - if (!COMPAT_USE_64BIT_TIME && - (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) + if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) return do_get_sock_timeout(sock, level, optname, optval, optlen); return sock_getsockopt(sock, level, optname, optval, optlen); } @@ -770,24 +767,14 @@ COMPAT_SYSCALL_DEFINE5(recvmmsg, int, fd, struct compat_mmsghdr __user *, mmsg, COMPAT_SYSCALL_DEFINE2(socketcall, int, call, u32 __user *, args) { - u32 a[AUDITSC_ARGS]; - unsigned int len; - u32 a0, a1; int ret; + u32 a[6]; + u32 a0, a1; if (call < SYS_SOCKET || call > SYS_SENDMMSG) return -EINVAL; - len = nas[call]; - if (len > sizeof(a)) - return -EINVAL; - - if (copy_from_user(a, args, len)) + if (copy_from_user(a, args, nas[call])) return -EFAULT; - - ret = audit_socketcall_compat(len / sizeof(a[0]), a); - if (ret) - return ret; - a0 = a[0]; a1 = a[1]; diff --git a/net/core/Makefile b/net/core/Makefile index 0d8ad4d0261b..086b01fbe1bd 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -24,4 +24,3 @@ obj-$(CONFIG_NET_PTP_CLASSIFY) += ptp_classifier.o obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o obj-$(CONFIG_LWTUNNEL) += lwtunnel.o -obj-$(CONFIG_DST_CACHE) += dst_cache.o diff --git a/net/core/dev.c b/net/core/dev.c index 65c5c9409949..81dc6c608c2b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -182,7 +182,7 @@ EXPORT_SYMBOL(dev_base_lock); /* protects napi_hash addition/deletion and napi_gen_id */ static DEFINE_SPINLOCK(napi_hash_lock); -static unsigned int napi_gen_id = NR_CPUS; +static unsigned int napi_gen_id; static DEFINE_HASHTABLE(napi_hash, 8); static seqcount_t devnet_rename_seq; @@ -989,7 +989,7 @@ bool dev_valid_name(const char *name) { if (*name == '\0') return false; - if (strnlen(name, IFNAMSIZ) == IFNAMSIZ) + if (strlen(name) >= IFNAMSIZ) return false; if (!strcmp(name, ".") || !strcmp(name, "..")) return false; @@ -1111,8 +1111,9 @@ static int dev_alloc_name_ns(struct net *net, return ret; } -int dev_get_valid_name(struct net *net, struct net_device *dev, - const char *name) +static int dev_get_valid_name(struct net *net, + struct net_device *dev, + const char *name) { BUG_ON(!net); @@ -1128,7 +1129,6 @@ int dev_get_valid_name(struct net *net, struct net_device *dev, return 0; } -EXPORT_SYMBOL(dev_get_valid_name); /** * dev_change_name - change name of a device @@ -1246,9 +1246,8 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) if (!new_ifalias) return -ENOMEM; dev->ifalias = new_ifalias; - memcpy(dev->ifalias, alias, len); - dev->ifalias[len] = 0; + strlcpy(dev->ifalias, alias, len+1); return len; } @@ -1300,7 +1299,6 @@ void netdev_notify_peers(struct net_device *dev) { rtnl_lock(); call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev); - call_netdevice_notifiers(NETDEV_RESEND_IGMP, dev); rtnl_unlock(); } EXPORT_SYMBOL(netdev_notify_peers); @@ -1678,59 +1676,37 @@ EXPORT_SYMBOL_GPL(net_dec_ingress_queue); static struct static_key netstamp_needed __read_mostly; #ifdef HAVE_JUMP_LABEL +/* We are not allowed to call static_key_slow_dec() from irq context + * If net_disable_timestamp() is called from irq context, defer the + * static_key_slow_dec() calls. + */ static atomic_t netstamp_needed_deferred; -static atomic_t netstamp_wanted; -static void netstamp_clear(struct work_struct *work) -{ - int deferred = atomic_xchg(&netstamp_needed_deferred, 0); - int wanted; - - wanted = atomic_add_return(deferred, &netstamp_wanted); - if (wanted > 0) - static_key_enable(&netstamp_needed); - else - static_key_disable(&netstamp_needed); -} -static DECLARE_WORK(netstamp_work, netstamp_clear); #endif void net_enable_timestamp(void) { #ifdef HAVE_JUMP_LABEL - int wanted; + int deferred = atomic_xchg(&netstamp_needed_deferred, 0); - while (1) { - wanted = atomic_read(&netstamp_wanted); - if (wanted <= 0) - break; - if (atomic_cmpxchg(&netstamp_wanted, wanted, wanted + 1) == wanted) - return; + if (deferred) { + while (--deferred) + static_key_slow_dec(&netstamp_needed); + return; } - atomic_inc(&netstamp_needed_deferred); - schedule_work(&netstamp_work); -#else - static_key_slow_inc(&netstamp_needed); #endif + static_key_slow_inc(&netstamp_needed); } EXPORT_SYMBOL(net_enable_timestamp); void net_disable_timestamp(void) { #ifdef HAVE_JUMP_LABEL - int wanted; - - while (1) { - wanted = atomic_read(&netstamp_wanted); - if (wanted <= 1) - break; - if (atomic_cmpxchg(&netstamp_wanted, wanted, wanted - 1) == wanted) - return; + if (in_interrupt()) { + atomic_inc(&netstamp_needed_deferred); + return; } - atomic_dec(&netstamp_needed_deferred); - schedule_work(&netstamp_work); -#else - static_key_slow_dec(&netstamp_needed); #endif + static_key_slow_dec(&netstamp_needed); } EXPORT_SYMBOL(net_disable_timestamp); @@ -2183,11 +2159,8 @@ EXPORT_SYMBOL(netif_set_xps_queue); */ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) { - bool disabling; int rc; - disabling = txq < dev->real_num_tx_queues; - if (txq < 1 || txq > dev->num_tx_queues) return -EINVAL; @@ -2203,19 +2176,15 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) if (dev->num_tc) netif_setup_tc(dev, txq); - dev->real_num_tx_queues = txq; - - if (disabling) { - synchronize_net(); + if (txq < dev->real_num_tx_queues) { qdisc_reset_all_tx_gt(dev, txq); #ifdef CONFIG_XPS netif_reset_xps_queues_gt(dev, txq); #endif } - } else { - dev->real_num_tx_queues = txq; } + dev->real_num_tx_queues = txq; return 0; } EXPORT_SYMBOL(netif_set_real_num_tx_queues); @@ -2346,9 +2315,6 @@ void __dev_kfree_skb_irq(struct sk_buff *skb, enum skb_free_reason reason) { unsigned long flags; - if (unlikely(!skb)) - return; - if (likely(atomic_read(&skb->users) == 1)) { smp_rmb(); atomic_set(&skb->users, 0); @@ -2496,7 +2462,7 @@ int skb_checksum_help(struct sk_buff *skb) goto out; } - *(__sum16 *)(skb->data + offset) = csum_fold(csum) ?: CSUM_MANGLED_0; + *(__sum16 *)(skb->data + offset) = csum_fold(csum); out_set_summed: skb->ip_summed = CHECKSUM_NONE; out: @@ -2515,7 +2481,7 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth) if (unlikely(!pskb_may_pull(skb, sizeof(struct ethhdr)))) return 0; - eth = (struct ethhdr *)skb->data; + eth = (struct ethhdr *)skb_mac_header(skb); type = eth->h_proto; } @@ -2561,10 +2527,9 @@ EXPORT_SYMBOL(skb_mac_gso_segment); static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path) { if (tx_path) - return skb->ip_summed != CHECKSUM_PARTIAL && - skb->ip_summed != CHECKSUM_UNNECESSARY; - - return skb->ip_summed == CHECKSUM_NONE; + return skb->ip_summed != CHECKSUM_PARTIAL; + else + return skb->ip_summed == CHECKSUM_NONE; } /** @@ -2583,12 +2548,11 @@ static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path) struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t features, bool tx_path) { - struct sk_buff *segs; - if (unlikely(skb_needs_check(skb, tx_path))) { int err; - /* We're going to init ->check field in TCP or UDP header */ + skb_warn_bad_offload(skb); + err = skb_cow_head(skb, 0); if (err < 0) return ERR_PTR(err); @@ -2603,12 +2567,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, skb_reset_mac_header(skb); skb_reset_mac_len(skb); - segs = skb_mac_gso_segment(skb, features); - - if (unlikely(skb_needs_check(skb, tx_path) && !IS_ERR(segs))) - skb_warn_bad_offload(skb); - - return segs; + return skb_mac_gso_segment(skb, features); } EXPORT_SYMBOL(__skb_gso_segment); @@ -2691,9 +2650,9 @@ static netdev_features_t harmonize_features(struct sk_buff *skb, if (skb->ip_summed != CHECKSUM_NONE && !can_checksum_protocol(features, type)) { features &= ~NETIF_F_ALL_CSUM; - } - if (illegal_highdma(skb->dev, skb)) + } else if (illegal_highdma(skb->dev, skb)) { features &= ~NETIF_F_SG; + } return features; } @@ -2706,7 +2665,7 @@ netdev_features_t passthru_features_check(struct sk_buff *skb, } EXPORT_SYMBOL(passthru_features_check); -static netdev_features_t dflt_features_check(struct sk_buff *skb, +static netdev_features_t dflt_features_check(const struct sk_buff *skb, struct net_device *dev, netdev_features_t features) { @@ -2877,7 +2836,6 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d } return head; } -EXPORT_SYMBOL_GPL(validate_xmit_skb_list); static void qdisc_pkt_len_init(struct sk_buff *skb) { @@ -2896,21 +2854,10 @@ static void qdisc_pkt_len_init(struct sk_buff *skb) hdr_len = skb_transport_header(skb) - skb_mac_header(skb); /* + transport layer */ - if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) { - const struct tcphdr *th; - struct tcphdr _tcphdr; - - th = skb_header_pointer(skb, skb_transport_offset(skb), - sizeof(_tcphdr), &_tcphdr); - if (likely(th)) - hdr_len += __tcp_hdrlen(th); - } else { - struct udphdr _udphdr; - - if (skb_header_pointer(skb, skb_transport_offset(skb), - sizeof(_udphdr), &_udphdr)) - hdr_len += sizeof(struct udphdr); - } + if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) + hdr_len += tcp_hdrlen(skb); + else + hdr_len += sizeof(struct udphdr); if (shinfo->gso_type & SKB_GSO_DODGY) gso_segs = DIV_ROUND_UP(skb->len - hdr_len, @@ -3079,9 +3026,7 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev, int queue_index = 0; #ifdef CONFIG_XPS - u32 sender_cpu = skb->sender_cpu - 1; - - if (sender_cpu >= (u32)NR_CPUS) + if (skb->sender_cpu == 0) skb->sender_cpu = raw_smp_processor_id() + 1; #endif @@ -3776,22 +3721,6 @@ static inline struct sk_buff *handle_ing(struct sk_buff *skb, return skb; } -/** - * netdev_is_rx_handler_busy - check if receive handler is registered - * @dev: device to check - * - * Check if a receive handler is already registered for a given device. - * Return true if there one. - * - * The caller must hold the rtnl_mutex. - */ -bool netdev_is_rx_handler_busy(struct net_device *dev) -{ - ASSERT_RTNL(); - return dev && rtnl_dereference(dev->rx_handler); -} -EXPORT_SYMBOL_GPL(netdev_is_rx_handler_busy); - /** * netdev_rx_handler_register - register receive handler * @dev: device to register a handler for @@ -4241,9 +4170,7 @@ static void skb_gro_reset_offset(struct sk_buff *skb) pinfo->nr_frags && !PageHighMem(skb_frag_page(frag0))) { NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0); - NAPI_GRO_CB(skb)->frag0_len = min_t(unsigned int, - skb_frag_size(frag0), - skb->end - skb->tail); + NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(frag0); } } @@ -4297,7 +4224,6 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff NAPI_GRO_CB(skb)->flush = 0; NAPI_GRO_CB(skb)->free = 0; NAPI_GRO_CB(skb)->encap_mark = 0; - NAPI_GRO_CB(skb)->recursion_counter = 0; NAPI_GRO_CB(skb)->gro_remcsum_start = 0; /* Setup for GRO checksum validation */ @@ -4404,12 +4330,6 @@ struct packet_offload *gro_find_complete_by_type(__be16 type) } EXPORT_SYMBOL(gro_find_complete_by_type); -static void napi_skb_free_stolen_head(struct sk_buff *skb) -{ - skb_dst_drop(skb); - kmem_cache_free(skbuff_head_cache, skb); -} - static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb) { switch (ret) { @@ -4423,10 +4343,12 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb) break; case GRO_MERGED_FREE: - if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) - napi_skb_free_stolen_head(skb); - else + if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) { + skb_dst_drop(skb); + kmem_cache_free(skbuff_head_cache, skb); + } else { __kfree_skb(skb); + } break; case GRO_HELD: @@ -4492,14 +4414,8 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi, break; case GRO_DROP: - napi_reuse_skb(napi, skb); - break; - case GRO_MERGED_FREE: - if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) - napi_skb_free_stolen_head(skb); - else - napi_reuse_skb(napi, skb); + napi_reuse_skb(napi, skb); break; case GRO_MERGED: @@ -4776,22 +4692,25 @@ EXPORT_SYMBOL_GPL(napi_by_id); void napi_hash_add(struct napi_struct *napi) { - if (test_and_set_bit(NAPI_STATE_HASHED, &napi->state)) - return; + if (!test_and_set_bit(NAPI_STATE_HASHED, &napi->state)) { - spin_lock(&napi_hash_lock); + spin_lock(&napi_hash_lock); - /* 0..NR_CPUS+1 range is reserved for sender_cpu use */ - do { - if (unlikely(++napi_gen_id < NR_CPUS + 1)) - napi_gen_id = NR_CPUS + 1; - } while (napi_by_id(napi_gen_id)); - napi->napi_id = napi_gen_id; + /* 0 is not a valid id, we also skip an id that is taken + * we expect both events to be extremely rare + */ + napi->napi_id = 0; + while (!napi->napi_id) { + napi->napi_id = ++napi_gen_id; + if (napi_by_id(napi->napi_id)) + napi->napi_id = 0; + } - hlist_add_head_rcu(&napi->napi_hash_node, - &napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]); + hlist_add_head_rcu(&napi->napi_hash_node, + &napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]); - spin_unlock(&napi_hash_lock); + spin_unlock(&napi_hash_lock); + } } EXPORT_SYMBOL_GPL(napi_hash_add); @@ -5277,7 +5196,6 @@ static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev, static int __netdev_adjacent_dev_insert(struct net_device *dev, struct net_device *adj_dev, - u16 ref_nr, struct list_head *dev_list, void *private, bool master) { @@ -5287,7 +5205,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, adj = __netdev_find_adj(adj_dev, dev_list); if (adj) { - adj->ref_nr += ref_nr; + adj->ref_nr++; return 0; } @@ -5297,7 +5215,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, adj->dev = adj_dev; adj->master = master; - adj->ref_nr = ref_nr; + adj->ref_nr = 1; adj->private = private; dev_hold(adj_dev); @@ -5336,7 +5254,6 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, static void __netdev_adjacent_dev_remove(struct net_device *dev, struct net_device *adj_dev, - u16 ref_nr, struct list_head *dev_list) { struct netdev_adjacent *adj; @@ -5349,10 +5266,10 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, BUG(); } - if (adj->ref_nr > ref_nr) { - pr_debug("%s to %s ref_nr-%d = %d\n", dev->name, adj_dev->name, - ref_nr, adj->ref_nr-ref_nr); - adj->ref_nr -= ref_nr; + if (adj->ref_nr > 1) { + pr_debug("%s to %s ref_nr-- = %d\n", dev->name, adj_dev->name, + adj->ref_nr-1); + adj->ref_nr--; return; } @@ -5371,22 +5288,21 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, static int __netdev_adjacent_dev_link_lists(struct net_device *dev, struct net_device *upper_dev, - u16 ref_nr, struct list_head *up_list, struct list_head *down_list, void *private, bool master) { int ret; - ret = __netdev_adjacent_dev_insert(dev, upper_dev, ref_nr, up_list, - private, master); + ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, private, + master); if (ret) return ret; - ret = __netdev_adjacent_dev_insert(upper_dev, dev, ref_nr, down_list, - private, false); + ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, private, + false); if (ret) { - __netdev_adjacent_dev_remove(dev, upper_dev, ref_nr, up_list); + __netdev_adjacent_dev_remove(dev, upper_dev, up_list); return ret; } @@ -5394,10 +5310,9 @@ static int __netdev_adjacent_dev_link_lists(struct net_device *dev, } static int __netdev_adjacent_dev_link(struct net_device *dev, - struct net_device *upper_dev, - u16 ref_nr) + struct net_device *upper_dev) { - return __netdev_adjacent_dev_link_lists(dev, upper_dev, ref_nr, + return __netdev_adjacent_dev_link_lists(dev, upper_dev, &dev->all_adj_list.upper, &upper_dev->all_adj_list.lower, NULL, false); @@ -5405,19 +5320,17 @@ static int __netdev_adjacent_dev_link(struct net_device *dev, static void __netdev_adjacent_dev_unlink_lists(struct net_device *dev, struct net_device *upper_dev, - u16 ref_nr, struct list_head *up_list, struct list_head *down_list) { - __netdev_adjacent_dev_remove(dev, upper_dev, ref_nr, up_list); - __netdev_adjacent_dev_remove(upper_dev, dev, ref_nr, down_list); + __netdev_adjacent_dev_remove(dev, upper_dev, up_list); + __netdev_adjacent_dev_remove(upper_dev, dev, down_list); } static void __netdev_adjacent_dev_unlink(struct net_device *dev, - struct net_device *upper_dev, - u16 ref_nr) + struct net_device *upper_dev) { - __netdev_adjacent_dev_unlink_lists(dev, upper_dev, ref_nr, + __netdev_adjacent_dev_unlink_lists(dev, upper_dev, &dev->all_adj_list.upper, &upper_dev->all_adj_list.lower); } @@ -5426,17 +5339,17 @@ static int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, struct net_device *upper_dev, void *private, bool master) { - int ret = __netdev_adjacent_dev_link(dev, upper_dev, 1); + int ret = __netdev_adjacent_dev_link(dev, upper_dev); if (ret) return ret; - ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, 1, + ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, &dev->adj_list.upper, &upper_dev->adj_list.lower, private, master); if (ret) { - __netdev_adjacent_dev_unlink(dev, upper_dev, 1); + __netdev_adjacent_dev_unlink(dev, upper_dev); return ret; } @@ -5446,8 +5359,8 @@ static int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, static void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev, struct net_device *upper_dev) { - __netdev_adjacent_dev_unlink(dev, upper_dev, 1); - __netdev_adjacent_dev_unlink_lists(dev, upper_dev, 1, + __netdev_adjacent_dev_unlink(dev, upper_dev); + __netdev_adjacent_dev_unlink_lists(dev, upper_dev, &dev->adj_list.upper, &upper_dev->adj_list.lower); } @@ -5499,7 +5412,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) { pr_debug("Interlinking %s with %s, non-neighbour\n", i->dev->name, j->dev->name); - ret = __netdev_adjacent_dev_link(i->dev, j->dev, i->ref_nr); + ret = __netdev_adjacent_dev_link(i->dev, j->dev); if (ret) goto rollback_mesh; } @@ -5509,7 +5422,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) { pr_debug("linking %s's upper device %s with %s\n", upper_dev->name, i->dev->name, dev->name); - ret = __netdev_adjacent_dev_link(dev, i->dev, i->ref_nr); + ret = __netdev_adjacent_dev_link(dev, i->dev); if (ret) goto rollback_upper_mesh; } @@ -5518,7 +5431,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, list_for_each_entry(i, &dev->all_adj_list.lower, list) { pr_debug("linking %s's lower device %s with %s\n", dev->name, i->dev->name, upper_dev->name); - ret = __netdev_adjacent_dev_link(i->dev, upper_dev, i->ref_nr); + ret = __netdev_adjacent_dev_link(i->dev, upper_dev); if (ret) goto rollback_lower_mesh; } @@ -5532,7 +5445,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, list_for_each_entry(i, &dev->all_adj_list.lower, list) { if (i == to_i) break; - __netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr); + __netdev_adjacent_dev_unlink(i->dev, upper_dev); } i = NULL; @@ -5542,7 +5455,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) { if (i == to_i) break; - __netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr); + __netdev_adjacent_dev_unlink(dev, i->dev); } i = j = NULL; @@ -5554,7 +5467,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) { if (i == to_i && j == to_j) break; - __netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr); + __netdev_adjacent_dev_unlink(i->dev, j->dev); } if (i == to_i) break; @@ -5638,16 +5551,16 @@ void netdev_upper_dev_unlink(struct net_device *dev, */ list_for_each_entry(i, &dev->all_adj_list.lower, list) list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) - __netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr); + __netdev_adjacent_dev_unlink(i->dev, j->dev); /* remove also the devices itself from lower/upper device * list */ list_for_each_entry(i, &dev->all_adj_list.lower, list) - __netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr); + __netdev_adjacent_dev_unlink(i->dev, upper_dev); list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) - __netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr); + __netdev_adjacent_dev_unlink(dev, i->dev); call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev, &changeupper_info.info); @@ -7103,8 +7016,8 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, } else { netdev_stats_to_stats64(storage, &dev->stats); } - storage->rx_dropped += (unsigned long)atomic_long_read(&dev->rx_dropped); - storage->tx_dropped += (unsigned long)atomic_long_read(&dev->tx_dropped); + storage->rx_dropped += atomic_long_read(&dev->rx_dropped); + storage->tx_dropped += atomic_long_read(&dev->tx_dropped); return storage; } EXPORT_SYMBOL(dev_get_stats); @@ -7432,8 +7345,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* We get here if we can't use the current device name */ if (!pat) goto out; - err = dev_get_valid_name(net, dev, pat); - if (err < 0) + if (dev_get_valid_name(net, dev, pat) < 0) goto out; } @@ -7445,6 +7357,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char dev_close(dev); /* And unlink it from device chain */ + err = -ENODEV; unlist_netdevice(dev); synchronize_net(); diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index e3e6a3e2ca22..c0548d268e1a 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -57,8 +57,8 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list, return -EINVAL; list_for_each_entry(ha, &list->list, list) { - if (ha->type == addr_type && - !memcmp(ha->addr, addr, addr_len)) { + if (!memcmp(ha->addr, addr, addr_len) && + ha->type == addr_type) { if (global) { /* check if addr is already used as global */ if (ha->global_use) diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c index 151e047ce072..b94b1d293506 100644 --- a/net/core/dev_ioctl.c +++ b/net/core/dev_ioctl.c @@ -28,7 +28,6 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg) if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) return -EFAULT; - ifr.ifr_name[IFNAMSIZ-1] = 0; error = netdev_get_name(net, ifr.ifr_name, ifr.ifr_ifindex); if (error) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index a2270188b864..252e155c837b 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -80,7 +80,6 @@ static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data) struct nlattr *nla; struct sk_buff *skb; unsigned long flags; - void *msg_header; al = sizeof(struct net_dm_alert_msg); al += dm_hit_limit * sizeof(struct net_dm_drop_point); @@ -88,41 +87,21 @@ static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data) skb = genlmsg_new(al, GFP_KERNEL); - if (!skb) - goto err; - - msg_header = genlmsg_put(skb, 0, 0, &net_drop_monitor_family, - 0, NET_DM_CMD_ALERT); - if (!msg_header) { - nlmsg_free(skb); - skb = NULL; - goto err; - } - nla = nla_reserve(skb, NLA_UNSPEC, - sizeof(struct net_dm_alert_msg)); - if (!nla) { - nlmsg_free(skb); - skb = NULL; - goto err; + if (skb) { + genlmsg_put(skb, 0, 0, &net_drop_monitor_family, + 0, NET_DM_CMD_ALERT); + nla = nla_reserve(skb, NLA_UNSPEC, + sizeof(struct net_dm_alert_msg)); + msg = nla_data(nla); + memset(msg, 0, al); + } else { + mod_timer(&data->send_timer, jiffies + HZ / 10); } - msg = nla_data(nla); - memset(msg, 0, al); - goto out; -err: - mod_timer(&data->send_timer, jiffies + HZ / 10); -out: spin_lock_irqsave(&data->lock, flags); swap(data->skb, skb); spin_unlock_irqrestore(&data->lock, flags); - if (skb) { - struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data; - struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlh); - - genlmsg_end(skb, genlmsg_data(gnlh)); - } - return skb; } diff --git a/net/core/dst.c b/net/core/dst.c index e72d706f8d0c..a1656e3b8d72 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -151,13 +151,13 @@ int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb) } EXPORT_SYMBOL(dst_discard_out); -const struct dst_metrics dst_default_metrics = { +const u32 dst_default_metrics[RTAX_MAX + 1] = { /* This initializer is needed to force linker to place this variable * into const section. Otherwise it might end into bss section. * We really want to avoid false sharing on this variable, and catch * any writes on it. */ - .refcnt = ATOMIC_INIT(1), + [RTAX_MAX] = 0xdeadbeef, }; void dst_init(struct dst_entry *dst, struct dst_ops *ops, @@ -169,7 +169,7 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops, if (dev) dev_hold(dev); dst->ops = ops; - dst_init_metrics(dst, dst_default_metrics.metrics, true); + dst_init_metrics(dst, dst_default_metrics, true); dst->expires = 0UL; dst->path = dst; dst->from = NULL; @@ -315,30 +315,25 @@ EXPORT_SYMBOL(dst_release); u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old) { - struct dst_metrics *p = kmalloc(sizeof(*p), GFP_ATOMIC); + u32 *p = kmalloc(sizeof(u32) * RTAX_MAX, GFP_ATOMIC); if (p) { - struct dst_metrics *old_p = (struct dst_metrics *)__DST_METRICS_PTR(old); + u32 *old_p = __DST_METRICS_PTR(old); unsigned long prev, new; - atomic_set(&p->refcnt, 1); - memcpy(p->metrics, old_p->metrics, sizeof(p->metrics)); + memcpy(p, old_p, sizeof(u32) * RTAX_MAX); new = (unsigned long) p; prev = cmpxchg(&dst->_metrics, old, new); if (prev != old) { kfree(p); - p = (struct dst_metrics *)__DST_METRICS_PTR(prev); + p = __DST_METRICS_PTR(prev); if (prev & DST_METRICS_READ_ONLY) p = NULL; - } else if (prev & DST_METRICS_REFCOUNTED) { - if (atomic_dec_and_test(&old_p->refcnt)) - kfree(old_p); } } - BUILD_BUG_ON(offsetof(struct dst_metrics, metrics) != 0); - return (u32 *)p; + return p; } EXPORT_SYMBOL(dst_cow_metrics_generic); @@ -347,7 +342,7 @@ void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old) { unsigned long prev, new; - new = ((unsigned long) &dst_default_metrics) | DST_METRICS_READ_ONLY; + new = ((unsigned long) dst_default_metrics) | DST_METRICS_READ_ONLY; prev = cmpxchg(&dst->_metrics, old, new); if (prev == old) kfree(__DST_METRICS_PTR(old)); @@ -462,20 +457,6 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, spin_lock_bh(&dst_garbage.lock); dst = dst_garbage.list; dst_garbage.list = NULL; - /* The code in dst_ifdown places a hold on the loopback device. - * If the gc entry processing is set to expire after a lengthy - * interval, this hold can cause netdev_wait_allrefs() to hang - * out and wait for a long time -- until the the loopback - * interface is released. If we're really unlucky, it'll emit - * pr_emerg messages to console too. Reset the interval here, - * so dst cleanups occur in a more timely fashion. - */ - if (dst_garbage.timer_inc > DST_GC_INC) { - dst_garbage.timer_inc = DST_GC_INC; - dst_garbage.timer_expires = DST_GC_MIN; - mod_delayed_work(system_wq, &dst_gc_work, - dst_garbage.timer_expires); - } spin_unlock_bh(&dst_garbage.lock); if (last) diff --git a/net/core/dst_cache.c b/net/core/dst_cache.c deleted file mode 100644 index 554d36449231..000000000000 --- a/net/core/dst_cache.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * net/core/dst_cache.c - dst entry cache - * - * Copyright (c) 2016 Paolo Abeni - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#if IS_ENABLED(CONFIG_IPV6) -#include -#endif -#include - -struct dst_cache_pcpu { - unsigned long refresh_ts; - struct dst_entry *dst; - u32 cookie; - union { - struct in_addr in_saddr; - struct in6_addr in6_saddr; - }; -}; - -static void dst_cache_per_cpu_dst_set(struct dst_cache_pcpu *dst_cache, - struct dst_entry *dst, u32 cookie) -{ - dst_release(dst_cache->dst); - if (dst) - dst_hold(dst); - - dst_cache->cookie = cookie; - dst_cache->dst = dst; -} - -static struct dst_entry *dst_cache_per_cpu_get(struct dst_cache *dst_cache, - struct dst_cache_pcpu *idst) -{ - struct dst_entry *dst; - - dst = idst->dst; - if (!dst) - goto fail; - - /* the cache already hold a dst reference; it can't go away */ - dst_hold(dst); - - if (unlikely(!time_after(idst->refresh_ts, dst_cache->reset_ts) || - (dst->obsolete && !dst->ops->check(dst, idst->cookie)))) { - dst_cache_per_cpu_dst_set(idst, NULL, 0); - dst_release(dst); - goto fail; - } - return dst; - -fail: - idst->refresh_ts = jiffies; - return NULL; -} - -struct dst_entry *dst_cache_get(struct dst_cache *dst_cache) -{ - if (!dst_cache->cache) - return NULL; - - return dst_cache_per_cpu_get(dst_cache, this_cpu_ptr(dst_cache->cache)); -} -EXPORT_SYMBOL_GPL(dst_cache_get); - -struct rtable *dst_cache_get_ip4(struct dst_cache *dst_cache, __be32 *saddr) -{ - struct dst_cache_pcpu *idst; - struct dst_entry *dst; - - if (!dst_cache->cache) - return NULL; - - idst = this_cpu_ptr(dst_cache->cache); - dst = dst_cache_per_cpu_get(dst_cache, idst); - if (!dst) - return NULL; - - *saddr = idst->in_saddr.s_addr; - return container_of(dst, struct rtable, dst); -} -EXPORT_SYMBOL_GPL(dst_cache_get_ip4); - -void dst_cache_set_ip4(struct dst_cache *dst_cache, struct dst_entry *dst, - __be32 saddr) -{ - struct dst_cache_pcpu *idst; - - if (!dst_cache->cache) - return; - - idst = this_cpu_ptr(dst_cache->cache); - dst_cache_per_cpu_dst_set(idst, dst, 0); - idst->in_saddr.s_addr = saddr; -} -EXPORT_SYMBOL_GPL(dst_cache_set_ip4); - -#if IS_ENABLED(CONFIG_IPV6) -void dst_cache_set_ip6(struct dst_cache *dst_cache, struct dst_entry *dst, - const struct in6_addr *addr) -{ - struct dst_cache_pcpu *idst; - - if (!dst_cache->cache) - return; - - idst = this_cpu_ptr(dst_cache->cache); - dst_cache_per_cpu_dst_set(this_cpu_ptr(dst_cache->cache), dst, - rt6_get_cookie((struct rt6_info *)dst)); - idst->in6_saddr = *addr; -} -EXPORT_SYMBOL_GPL(dst_cache_set_ip6); - -struct dst_entry *dst_cache_get_ip6(struct dst_cache *dst_cache, - struct in6_addr *saddr) -{ - struct dst_cache_pcpu *idst; - struct dst_entry *dst; - - if (!dst_cache->cache) - return NULL; - - idst = this_cpu_ptr(dst_cache->cache); - dst = dst_cache_per_cpu_get(dst_cache, idst); - if (!dst) - return NULL; - - *saddr = idst->in6_saddr; - return dst; -} -EXPORT_SYMBOL_GPL(dst_cache_get_ip6); -#endif - -int dst_cache_init(struct dst_cache *dst_cache, gfp_t gfp) -{ - dst_cache->cache = alloc_percpu_gfp(struct dst_cache_pcpu, - gfp | __GFP_ZERO); - if (!dst_cache->cache) - return -ENOMEM; - - dst_cache_reset(dst_cache); - return 0; -} -EXPORT_SYMBOL_GPL(dst_cache_init); - -void dst_cache_destroy(struct dst_cache *dst_cache) -{ - int i; - - if (!dst_cache->cache) - return; - - for_each_possible_cpu(i) - dst_release(per_cpu_ptr(dst_cache->cache, i)->dst); - - free_percpu(dst_cache->cache); -} -EXPORT_SYMBOL_GPL(dst_cache_destroy); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 02fe0a88c391..c271105d1cb3 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -886,12 +886,9 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) if (regs.len > reglen) regs.len = reglen; - regbuf = NULL; - if (reglen) { - regbuf = vzalloc(reglen); - if (!regbuf) - return -ENOMEM; - } + regbuf = vzalloc(reglen); + if (reglen && !regbuf) + return -ENOMEM; ops->get_regs(dev, ®s, regbuf); diff --git a/net/core/filter.c b/net/core/filter.c index 1a9ded6af138..f393a22b9d50 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -52,10 +52,9 @@ #include /** - * sk_filter_trim_cap - run a packet through a socket filter + * sk_filter - run a packet through a socket filter * @sk: sock associated with &sk_buff * @skb: buffer to filter - * @cap: limit on how short the eBPF program may trim the packet * * Run the eBPF program and then cut skb->data to correct size returned by * the program. If pkt_len is 0 we toss packet. If skb->len is smaller @@ -64,7 +63,7 @@ * be accepted or -EPERM if the packet should be tossed. * */ -int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap) +int sk_filter(struct sock *sk, struct sk_buff *skb) { int err; struct sk_filter *filter; @@ -85,13 +84,14 @@ int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap) filter = rcu_dereference(sk->sk_filter); if (filter) { unsigned int pkt_len = bpf_prog_run_save_cb(filter->prog, skb); - err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM; + + err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; } rcu_read_unlock(); return err; } -EXPORT_SYMBOL(sk_filter_trim_cap); +EXPORT_SYMBOL(sk_filter); static u64 __skb_get_pay_offset(u64 ctx, u64 a, u64 x, u64 r4, u64 r5) { @@ -430,10 +430,6 @@ static int bpf_convert_filter(struct sock_filter *prog, int len, convert_bpf_extensions(fp, &insn)) break; - if (fp->code == (BPF_ALU | BPF_DIV | BPF_X) || - fp->code == (BPF_ALU | BPF_MOD | BPF_X)) - *insn++ = BPF_MOV32_REG(BPF_REG_X, BPF_REG_X); - *insn = BPF_RAW_INSN(fp->code, BPF_REG_A, BPF_REG_X, 0, fp->k); break; @@ -988,9 +984,7 @@ static struct bpf_prog *bpf_migrate_filter(struct bpf_prog *fp) */ goto out_err_free; - err = bpf_prog_select_runtime(fp); - if (err) - goto out_err_free; + bpf_prog_select_runtime(fp); kfree(old_prog); return fp; @@ -1281,7 +1275,9 @@ static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags) */ if (unlikely((u32) offset > 0xffff || len > sizeof(buf))) return -EFAULT; - if (unlikely(skb_try_make_writable(skb, offset + len))) + + if (unlikely(skb_cloned(skb) && + !skb_clone_writable(skb, offset + len))) return -EFAULT; ptr = skb_header_pointer(skb, offset, len, buf); @@ -1325,7 +1321,8 @@ static u64 bpf_l3_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags) if (unlikely((u32) offset > 0xffff)) return -EFAULT; - if (unlikely(skb_try_make_writable(skb, offset + sizeof(sum)))) + if (unlikely(skb_cloned(skb) && + !skb_clone_writable(skb, offset + sizeof(sum)))) return -EFAULT; ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum); @@ -1370,7 +1367,9 @@ static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags) if (unlikely((u32) offset > 0xffff)) return -EFAULT; - if (unlikely(skb_try_make_writable(skb, offset + sizeof(sum)))) + + if (unlikely(skb_cloned(skb) && + !skb_clone_writable(skb, offset + sizeof(sum)))) return -EFAULT; ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum); @@ -1555,13 +1554,6 @@ bool bpf_helper_changes_skb_data(void *func) return true; if (func == bpf_skb_vlan_pop) return true; - if (func == bpf_skb_store_bytes) - return true; - if (func == bpf_l3_csum_replace) - return true; - if (func == bpf_l4_csum_replace) - return true; - return false; } diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 4d14908afaec..12e700332010 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -131,7 +131,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb, struct flow_dissector_key_tags *key_tags; struct flow_dissector_key_keyid *key_keyid; u8 ip_proto = 0; - bool ret; + bool ret = false; if (!data) { data = skb->data; @@ -492,16 +492,12 @@ bool __skb_flow_dissect(const struct sk_buff *skb, out_good: ret = true; -out: - key_control->thoff = min_t(u16, nhoff, skb ? skb->len : hlen); +out_bad: key_basic->n_proto = proto; key_basic->ip_proto = ip_proto; + key_control->thoff = (u16)nhoff; return ret; - -out_bad: - ret = false; - goto out; } EXPORT_SYMBOL(__skb_flow_dissect); @@ -666,23 +662,6 @@ void make_flow_keys_digest(struct flow_keys_digest *digest, } EXPORT_SYMBOL(make_flow_keys_digest); -static struct flow_dissector flow_keys_dissector_symmetric __read_mostly; - -u32 __skb_get_hash_symmetric(struct sk_buff *skb) -{ - struct flow_keys keys; - - __flow_hash_secret_init(); - - memset(&keys, 0, sizeof(keys)); - __skb_flow_dissect(skb, &flow_keys_dissector_symmetric, &keys, - NULL, 0, 0, 0, - FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL); - - return __flow_hash_from_keys(&keys, hashrnd); -} -EXPORT_SYMBOL_GPL(__skb_get_hash_symmetric); - /** * __skb_get_hash: calculate a flow hash * @skb: sk_buff to calculate flow hash from @@ -895,29 +874,6 @@ static const struct flow_dissector_key flow_keys_dissector_keys[] = { }, }; -static const struct flow_dissector_key flow_keys_dissector_symmetric_keys[] = { - { - .key_id = FLOW_DISSECTOR_KEY_CONTROL, - .offset = offsetof(struct flow_keys, control), - }, - { - .key_id = FLOW_DISSECTOR_KEY_BASIC, - .offset = offsetof(struct flow_keys, basic), - }, - { - .key_id = FLOW_DISSECTOR_KEY_IPV4_ADDRS, - .offset = offsetof(struct flow_keys, addrs.v4addrs), - }, - { - .key_id = FLOW_DISSECTOR_KEY_IPV6_ADDRS, - .offset = offsetof(struct flow_keys, addrs.v6addrs), - }, - { - .key_id = FLOW_DISSECTOR_KEY_PORTS, - .offset = offsetof(struct flow_keys, ports), - }, -}; - static const struct flow_dissector_key flow_keys_buf_dissector_keys[] = { { .key_id = FLOW_DISSECTOR_KEY_CONTROL, @@ -939,13 +895,10 @@ static int __init init_default_flow_dissectors(void) skb_flow_dissector_init(&flow_keys_dissector, flow_keys_dissector_keys, ARRAY_SIZE(flow_keys_dissector_keys)); - skb_flow_dissector_init(&flow_keys_dissector_symmetric, - flow_keys_dissector_symmetric_keys, - ARRAY_SIZE(flow_keys_dissector_symmetric_keys)); skb_flow_dissector_init(&flow_keys_buf_dissector, flow_keys_buf_dissector_keys, ARRAY_SIZE(flow_keys_buf_dissector_keys)); return 0; } -core_initcall(init_default_flow_dissectors); +late_initcall_sync(init_default_flow_dissectors); diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 642b13ddd69c..436822c109d5 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -54,8 +54,7 @@ do { \ static void neigh_timer_handler(unsigned long arg); static void __neigh_notify(struct neighbour *n, int type, int flags); static void neigh_update_notify(struct neighbour *neigh); -static int pneigh_ifdown_and_unlock(struct neigh_table *tbl, - struct net_device *dev); +static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev); #ifdef CONFIG_PROC_FS static const struct file_operations neigh_stat_seq_fops; @@ -255,7 +254,8 @@ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev) { write_lock_bh(&tbl->lock); neigh_flush_dev(tbl, dev); - pneigh_ifdown_and_unlock(tbl, dev); + pneigh_ifdown(tbl, dev); + write_unlock_bh(&tbl->lock); del_timer_sync(&tbl->proxy_timer); pneigh_queue_purge(&tbl->proxy_queue); @@ -496,7 +496,7 @@ struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey, if (atomic_read(&tbl->entries) > (1 << nht->hash_shift)) nht = neigh_hash_grow(tbl, nht->hash_shift + 1); - hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift); + hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift); if (n->parms->dead) { rc = ERR_PTR(-EINVAL); @@ -508,7 +508,7 @@ struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey, n1 != NULL; n1 = rcu_dereference_protected(n1->next, lockdep_is_held(&tbl->lock))) { - if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) { + if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) { if (want_ref) neigh_hold(n1); rc = n1; @@ -645,10 +645,9 @@ int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey, return -ENOENT; } -static int pneigh_ifdown_and_unlock(struct neigh_table *tbl, - struct net_device *dev) +static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev) { - struct pneigh_entry *n, **np, *freelist = NULL; + struct pneigh_entry *n, **np; u32 h; for (h = 0; h <= PNEIGH_HASHMASK; h++) { @@ -656,23 +655,16 @@ static int pneigh_ifdown_and_unlock(struct neigh_table *tbl, while ((n = *np) != NULL) { if (!dev || n->dev == dev) { *np = n->next; - n->next = freelist; - freelist = n; + if (tbl->pdestructor) + tbl->pdestructor(n); + if (n->dev) + dev_put(n->dev); + kfree(n); continue; } np = &n->next; } } - write_unlock_bh(&tbl->lock); - while ((n = freelist)) { - freelist = n->next; - n->next = NULL; - if (tbl->pdestructor) - tbl->pdestructor(n); - if (n->dev) - dev_put(n->dev); - kfree(n); - } return -ENOENT; } @@ -867,8 +859,7 @@ static void neigh_probe(struct neighbour *neigh) if (skb) skb = skb_clone(skb, GFP_ATOMIC); write_unlock(&neigh->lock); - if (neigh->ops->solicit) - neigh->ops->solicit(neigh, skb); + neigh->ops->solicit(neigh, skb); atomic_inc(&neigh->probes); kfree_skb(skb); } @@ -1140,6 +1131,10 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, lladdr = neigh->ha; } + if (new & NUD_CONNECTED) + neigh->confirmed = jiffies; + neigh->updated = jiffies; + /* If entry was valid and address is not changed, do not change entry state, if new one is STALE. */ @@ -1163,16 +1158,6 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, } } - /* Update timestamps only once we know we will make a change to the - * neighbour entry. Otherwise we risk to move the locktime window with - * noop updates and ignore relevant ARP updates. - */ - if (new != old || lladdr != neigh->ha) { - if (new & NUD_CONNECTED) - neigh->confirmed = jiffies; - neigh->updated = jiffies; - } - if (new != old) { neigh_del_timer(neigh); if (new & NUD_PROBE) @@ -2288,16 +2273,12 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL); if (!err) { - if (tb[NDA_IFINDEX]) { - if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32)) - return -EINVAL; + if (tb[NDA_IFINDEX]) filter_idx = nla_get_u32(tb[NDA_IFINDEX]); - } - if (tb[NDA_MASTER]) { - if (nla_len(tb[NDA_MASTER]) != sizeof(u32)) - return -EINVAL; + + if (tb[NDA_MASTER]) filter_master_idx = nla_get_u32(tb[NDA_MASTER]); - } + if (filter_idx || filter_master_idx) flags |= NLM_F_DUMP_FILTERED; } @@ -2486,17 +2467,13 @@ int neigh_xmit(int index, struct net_device *dev, tbl = neigh_tables[index]; if (!tbl) goto out; - rcu_read_lock_bh(); neigh = __neigh_lookup_noref(tbl, addr, dev); if (!neigh) neigh = __neigh_create(tbl, addr, dev, false); err = PTR_ERR(neigh); - if (IS_ERR(neigh)) { - rcu_read_unlock_bh(); + if (IS_ERR(neigh)) goto out_kfree_skb; - } err = neigh->output(neigh, skb); - rcu_read_unlock_bh(); } else if (index == NEIGH_LINK_TABLE) { err = dev_hard_header(skb, dev, ntohs(skb->protocol), diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index ccd20669ac00..ba6333c7dde3 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -217,8 +217,6 @@ int peernet2id_alloc(struct net *net, struct net *peer) bool alloc; int id; - if (atomic_read(&net->count) == 0) - return NETNSA_NSID_NOT_ASSIGNED; spin_lock_irqsave(&net->nsid_lock, flags); alloc = atomic_read(&peer->count) == 0 ? false : true; id = __peernet2id_alloc(net, peer, &alloc); @@ -310,25 +308,6 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns) goto out; } -static int __net_init net_defaults_init_net(struct net *net) -{ - net->core.sysctl_somaxconn = SOMAXCONN; - return 0; -} - -static struct pernet_operations net_defaults_ops = { - .init = net_defaults_init_net, -}; - -static __init int net_defaults_init(void) -{ - if (register_pernet_subsys(&net_defaults_ops)) - panic("Cannot initialize net default settings"); - - return 0; -} - -core_initcall(net_defaults_init); #ifdef CONFIG_NET_NS static struct kmem_cache *net_cachep; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 440aa9f6e0a8..94acfc89ad97 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -105,21 +105,15 @@ static void queue_process(struct work_struct *work) while ((skb = skb_dequeue(&npinfo->txq))) { struct net_device *dev = skb->dev; struct netdev_queue *txq; - unsigned int q_index; if (!netif_device_present(dev) || !netif_running(dev)) { kfree_skb(skb); continue; } + txq = skb_get_tx_queue(dev, skb); + local_irq_save(flags); - /* check if skb->queue_mapping is still valid */ - q_index = skb_get_queue_mapping(skb); - if (unlikely(q_index >= dev->real_num_tx_queues)) { - q_index = q_index % dev->real_num_tx_queues; - skb_set_queue_mapping(skb, q_index); - } - txq = netdev_get_tx_queue(dev, q_index); HARD_TX_LOCK(dev, txq, smp_processor_id()); if (netif_xmit_frozen_or_stopped(txq) || netpoll_start_xmit(skb, dev, txq) != NETDEV_TX_OK) { diff --git a/net/core/pktgen.c b/net/core/pktgen.c index b6327601f979..4da4d51a2ccf 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -215,8 +215,8 @@ #define M_NETIF_RECEIVE 1 /* Inject packets into stack */ /* If lock -- protects updating of if_list */ -#define if_lock(t) mutex_lock(&(t->if_lock)); -#define if_unlock(t) mutex_unlock(&(t->if_lock)); +#define if_lock(t) spin_lock(&(t->if_lock)); +#define if_unlock(t) spin_unlock(&(t->if_lock)); /* Used to help with determining the pkts on receive */ #define PKTGEN_MAGIC 0xbe9be955 @@ -422,7 +422,7 @@ struct pktgen_net { }; struct pktgen_thread { - struct mutex if_lock; /* for list of devices */ + spinlock_t if_lock; /* for list of devices */ struct list_head if_list; /* All device here */ struct list_head th_list; struct task_struct *tsk; @@ -2002,13 +2002,11 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d { struct pktgen_thread *t; - mutex_lock(&pktgen_thread_lock); - list_for_each_entry(t, &pn->pktgen_threads, th_list) { struct pktgen_dev *pkt_dev; - if_lock(t); - list_for_each_entry(pkt_dev, &t->if_list, list) { + rcu_read_lock(); + list_for_each_entry_rcu(pkt_dev, &t->if_list, list) { if (pkt_dev->odev != dev) continue; @@ -2023,9 +2021,8 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d dev->name); break; } - if_unlock(t); + rcu_read_unlock(); } - mutex_unlock(&pktgen_thread_lock); } static int pktgen_device_event(struct notifier_block *unused, @@ -2281,7 +2278,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) { - pkt_dev->pkt_overhead = 0; + pkt_dev->pkt_overhead = LL_RESERVED_SPACE(pkt_dev->odev); pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof(u32); pkt_dev->pkt_overhead += VLAN_TAG_SIZE(pkt_dev); pkt_dev->pkt_overhead += SVLAN_TAG_SIZE(pkt_dev); @@ -2772,13 +2769,13 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, } static struct sk_buff *pktgen_alloc_skb(struct net_device *dev, - struct pktgen_dev *pkt_dev) + struct pktgen_dev *pkt_dev, + unsigned int extralen) { - unsigned int extralen = LL_RESERVED_SPACE(dev); struct sk_buff *skb = NULL; - unsigned int size; + unsigned int size = pkt_dev->cur_pkt_size + 64 + extralen + + pkt_dev->pkt_overhead; - size = pkt_dev->cur_pkt_size + 64 + extralen + pkt_dev->pkt_overhead; if (pkt_dev->flags & F_NODE) { int node = pkt_dev->node >= 0 ? pkt_dev->node : numa_node_id(); @@ -2791,9 +2788,8 @@ static struct sk_buff *pktgen_alloc_skb(struct net_device *dev, skb = __netdev_alloc_skb(dev, size, GFP_NOWAIT); } - /* the caller pre-fetches from skb->data and reserves for the mac hdr */ if (likely(skb)) - skb_reserve(skb, extralen - 16); + skb_reserve(skb, LL_RESERVED_SPACE(dev)); return skb; } @@ -2826,14 +2822,16 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, mod_cur_headers(pkt_dev); queue_map = pkt_dev->cur_queue_map; - skb = pktgen_alloc_skb(odev, pkt_dev); + datalen = (odev->hard_header_len + 16) & ~0xf; + + skb = pktgen_alloc_skb(odev, pkt_dev, datalen); if (!skb) { sprintf(pkt_dev->result, "No memory"); return NULL; } prefetchw(skb->data); - skb_reserve(skb, 16); + skb_reserve(skb, datalen); /* Reserve for ethernet and IP header */ eth = (__u8 *) skb_push(skb, 14); @@ -2953,7 +2951,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, mod_cur_headers(pkt_dev); queue_map = pkt_dev->cur_queue_map; - skb = pktgen_alloc_skb(odev, pkt_dev); + skb = pktgen_alloc_skb(odev, pkt_dev, 16); if (!skb) { sprintf(pkt_dev->result, "No memory"); return NULL; @@ -3729,7 +3727,7 @@ static int __net_init pktgen_create_thread(int cpu, struct pktgen_net *pn) return -ENOMEM; } - mutex_init(&t->if_lock); + spin_lock_init(&t->if_lock); t->cpu = cpu; INIT_LIST_HEAD(&t->if_list); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 96c9c0f0905a..87b91ffbdec3 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -897,7 +897,6 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, + nla_total_size(1) /* IFLA_LINKMODE */ + nla_total_size(4) /* IFLA_CARRIER_CHANGES */ + nla_total_size(4) /* IFLA_LINK_NETNSID */ - + nla_total_size(4) /* IFLA_GROUP */ + nla_total_size(ext_filter_mask & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ @@ -1019,7 +1018,7 @@ static int rtnl_phys_port_name_fill(struct sk_buff *skb, struct net_device *dev) return err; } - if (nla_put_string(skb, IFLA_PHYS_PORT_NAME, name)) + if (nla_put(skb, IFLA_PHYS_PORT_NAME, strlen(name), name)) return -EMSGSIZE; return 0; @@ -1090,8 +1089,6 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, struct ifla_vf_mac vf_mac; struct ifla_vf_info ivi; - memset(&ivi, 0, sizeof(ivi)); - /* Not all SR-IOV capable drivers support the * spoofcheck and "RSS query enable" query. Preset to * -1 so the user space tool can detect that the driver @@ -1100,6 +1097,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, ivi.spoofchk = -1; ivi.rss_query_en = -1; ivi.trusted = -1; + memset(ivi.mac, 0, sizeof(ivi.mac)); /* The default value for VF link state is "auto" * IFLA_VF_LINK_STATE_AUTO which equals zero */ @@ -1372,7 +1370,6 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_PHYS_SWITCH_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN }, [IFLA_LINK_NETNSID] = { .type = NLA_S32 }, [IFLA_PROTO_DOWN] = { .type = NLA_U8 }, - [IFLA_GROUP] = { .type = NLA_U32 }, }; static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { @@ -1461,13 +1458,13 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) cb->nlh->nlmsg_seq, 0, NLM_F_MULTI, ext_filter_mask); + /* If we ran out of room on the first message, + * we're in trouble + */ + WARN_ON((err == -EMSGSIZE) && (skb->len == 0)); - if (err < 0) { - if (likely(skb->len)) - goto out; - - goto out_err; - } + if (err < 0) + goto out; nl_dump_check_consistent(cb, nlmsg_hdr(skb)); cont: @@ -1475,12 +1472,10 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) } } out: - err = skb->len; -out_err: cb->args[1] = idx; cb->args[0] = h; - return err; + return skb->len; } int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len) @@ -1691,10 +1686,6 @@ static int do_setlink(const struct sk_buff *skb, const struct net_device_ops *ops = dev->netdev_ops; int err; - err = validate_linkmsg(dev, tb); - if (err < 0) - return err; - if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) { struct net *net = rtnl_link_get_net(dev_net(dev), tb); if (IS_ERR(net)) { @@ -1746,8 +1737,7 @@ static int do_setlink(const struct sk_buff *skb, struct sockaddr *sa; int len; - len = sizeof(sa_family_t) + max_t(size_t, dev->addr_len, - sizeof(*sa)); + len = sizeof(sa_family_t) + dev->addr_len; sa = kmalloc(len, GFP_KERNEL); if (!sa) { err = -ENOMEM; @@ -1986,6 +1976,10 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh) goto errout; } + err = validate_linkmsg(dev, tb); + if (err < 0) + goto errout; + err = do_setlink(skb, dev, ifm, tb, ifname, 0); errout: return err; @@ -2087,12 +2081,9 @@ int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) return err; } - if (dev->rtnl_link_state == RTNL_LINK_INITIALIZED) { - __dev_notify_flags(dev, old_flags, 0U); - } else { - dev->rtnl_link_state = RTNL_LINK_INITIALIZED; - __dev_notify_flags(dev, old_flags, ~0U); - } + dev->rtnl_link_state = RTNL_LINK_INITIALIZED; + + __dev_notify_flags(dev, old_flags, ~0U); return 0; } EXPORT_SYMBOL(rtnl_configure_link); @@ -2609,10 +2600,7 @@ static int nlmsg_populate_fdb_fill(struct sk_buff *skb, static inline size_t rtnl_fdb_nlmsg_size(void) { - return NLMSG_ALIGN(sizeof(struct ndmsg)) + - nla_total_size(ETH_ALEN) + /* NDA_LLADDR */ - nla_total_size(sizeof(u16)) + /* NDA_VLAN */ - 0; + return NLMSG_ALIGN(sizeof(struct ndmsg)) + nla_total_size(ETH_ALEN); } static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, u16 vid, int type) @@ -3136,12 +3124,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) err = br_dev->netdev_ops->ndo_bridge_getlink( skb, portid, seq, dev, filter_mask, NLM_F_MULTI); - if (err < 0 && err != -EOPNOTSUPP) { - if (likely(skb->len)) - break; - - goto out_err; - } + if (err < 0 && err != -EOPNOTSUPP) + break; } idx++; } @@ -3152,22 +3136,16 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) seq, dev, filter_mask, NLM_F_MULTI); - if (err < 0 && err != -EOPNOTSUPP) { - if (likely(skb->len)) - break; - - goto out_err; - } + if (err < 0 && err != -EOPNOTSUPP) + break; } idx++; } } - err = skb->len; -out_err: rcu_read_unlock(); cb->args[0] = idx; - return err; + return skb->len; } static inline size_t bridge_nlmsg_size(void) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index a2e83e122821..ae4ead40b8cf 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -830,8 +830,6 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; n->cloned = 1; n->nohdr = 0; - n->peeked = 0; - C(pfmemalloc); n->destructor = NULL; C(tail); C(end); @@ -2559,8 +2557,7 @@ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len) { int pos = skb_headlen(skb); - skb_shinfo(skb1)->tx_flags |= skb_shinfo(skb)->tx_flags & - SKBTX_SHARED_FRAG; + skb_shinfo(skb1)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG; if (len < pos) /* Split line is inside header. */ skb_split_inside_header(skb, skb1, len, pos); else /* Second chunk has no header, nothing to copy. */ @@ -2956,6 +2953,24 @@ int skb_append_pagefrags(struct sk_buff *skb, struct page *page, } EXPORT_SYMBOL_GPL(skb_append_pagefrags); +/** + * skb_push_rcsum - push skb and update receive checksum + * @skb: buffer to update + * @len: length of data pulled + * + * This function performs an skb_push on the packet and updates + * the CHECKSUM_COMPLETE checksum. It should be used on + * receive path processing instead of skb_push unless you know + * that the checksum difference is zero (e.g., a valid IP header) + * or you are setting ip_summed to CHECKSUM_NONE. + */ +static unsigned char *skb_push_rcsum(struct sk_buff *skb, unsigned len) +{ + skb_push(skb, len); + skb_postpush_rcsum(skb, skb->data, len); + return skb->data; +} + /** * skb_pull_rcsum - pull skb and update receive checksum * @skb: buffer to update @@ -3124,8 +3139,8 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, skb_copy_from_linear_data_offset(head_skb, offset, skb_put(nskb, hsize), hsize); - skb_shinfo(nskb)->tx_flags |= skb_shinfo(head_skb)->tx_flags & - SKBTX_SHARED_FRAG; + skb_shinfo(nskb)->tx_flags = skb_shinfo(head_skb)->tx_flags & + SKBTX_SHARED_FRAG; while (pos < offset + len) { if (i >= nfrags) { @@ -3338,18 +3353,24 @@ void __init skb_init(void) NULL); } +/** + * skb_to_sgvec - Fill a scatter-gather list from a socket buffer + * @skb: Socket buffer containing the buffers to be mapped + * @sg: The scatter-gather list to map into + * @offset: The offset into the buffer's contents to start mapping + * @len: Length of buffer space to be mapped + * + * Fill the specified scatter-gather list with mappings/pointers into a + * region of the buffer space attached to a socket buffer. + */ static int -__skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len, - unsigned int recursion_level) +__skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) { int start = skb_headlen(skb); int i, copy = start - offset; struct sk_buff *frag_iter; int elt = 0; - if (unlikely(recursion_level >= 24)) - return -EMSGSIZE; - if (copy > 0) { if (copy > len) copy = len; @@ -3368,8 +3389,6 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len, end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]); if ((copy = end - offset) > 0) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - if (unlikely(elt && sg_is_last(&sg[elt - 1]))) - return -EMSGSIZE; if (copy > len) copy = len; @@ -3384,22 +3403,16 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len, } skb_walk_frags(skb, frag_iter) { - int end, ret; + int end; WARN_ON(start > offset + len); end = start + frag_iter->len; if ((copy = end - offset) > 0) { - if (unlikely(elt && sg_is_last(&sg[elt - 1]))) - return -EMSGSIZE; - if (copy > len) copy = len; - ret = __skb_to_sgvec(frag_iter, sg+elt, offset - start, - copy, recursion_level + 1); - if (unlikely(ret < 0)) - return ret; - elt += ret; + elt += __skb_to_sgvec(frag_iter, sg+elt, offset - start, + copy); if ((len -= copy) == 0) return elt; offset += copy; @@ -3410,31 +3423,6 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len, return elt; } -/** - * skb_to_sgvec - Fill a scatter-gather list from a socket buffer - * @skb: Socket buffer containing the buffers to be mapped - * @sg: The scatter-gather list to map into - * @offset: The offset into the buffer's contents to start mapping - * @len: Length of buffer space to be mapped - * - * Fill the specified scatter-gather list with mappings/pointers into a - * region of the buffer space attached to a socket buffer. Returns either - * the number of scatterlist items used, or -EMSGSIZE if the contents - * could not fit. - */ -int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) -{ - int nsg = __skb_to_sgvec(skb, sg, offset, len, 0); - - if (nsg <= 0) - return nsg; - - sg_mark_end(&sg[nsg - 1]); - - return nsg; -} -EXPORT_SYMBOL_GPL(skb_to_sgvec); - /* As compared with skb_to_sgvec, skb_to_sgvec_nomark only map skb to given * sglist without mark the sg which contain last skb data as the end. * So the caller can mannipulate sg list as will when padding new data after @@ -3457,11 +3445,19 @@ EXPORT_SYMBOL_GPL(skb_to_sgvec); int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) { - return __skb_to_sgvec(skb, sg, offset, len, 0); + return __skb_to_sgvec(skb, sg, offset, len); } EXPORT_SYMBOL_GPL(skb_to_sgvec_nomark); +int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) +{ + int nsg = __skb_to_sgvec(skb, sg, offset, len); + + sg_mark_end(&sg[nsg - 1]); + return nsg; +} +EXPORT_SYMBOL_GPL(skb_to_sgvec); /** * skb_cow_data - Check that a socket buffer's data buffers are writable @@ -3599,7 +3595,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) skb_queue_tail(&sk->sk_error_queue, skb); if (!sock_flag(sk, SOCK_DEAD)) - sk->sk_error_report(sk); + sk->sk_data_ready(sk); return 0; } EXPORT_SYMBOL(sock_queue_err_skb); @@ -3704,20 +3700,15 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, struct sock *sk = skb->sk; if (!skb_may_tx_timestamp(sk, false)) - goto err; - - /* Take a reference to prevent skb_orphan() from freeing the socket, - * but only if the socket refcount is not zero. - */ - if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) { - *skb_hwtstamps(skb) = *hwtstamps; - __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND); - sock_put(sk); return; - } -err: - kfree_skb(skb); + /* take a reference to prevent skb_orphan() from freeing the socket */ + sock_hold(sk); + + *skb_hwtstamps(skb) = *hwtstamps; + __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND); + + sock_put(sk); } EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp); @@ -3743,8 +3734,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, return; if (tsonly) { - skb_shinfo(skb)->tx_flags |= skb_shinfo(orig_skb)->tx_flags & - SKBTX_ANY_TSTAMP; + skb_shinfo(skb)->tx_flags = skb_shinfo(orig_skb)->tx_flags; skb_shinfo(skb)->tskey = skb_shinfo(orig_skb)->tskey; } @@ -3769,7 +3759,7 @@ void skb_complete_wifi_ack(struct sk_buff *skb, bool acked) { struct sock *sk = skb->sk; struct sock_exterr_skb *serr; - int err = 1; + int err; skb->wifi_acked_valid = 1; skb->wifi_acked = acked; @@ -3779,15 +3769,14 @@ void skb_complete_wifi_ack(struct sk_buff *skb, bool acked) serr->ee.ee_errno = ENOMSG; serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS; - /* Take a reference to prevent skb_orphan() from freeing the socket, - * but only if the socket refcount is not zero. - */ - if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) { - err = sock_queue_err_skb(sk, skb); - sock_put(sk); - } + /* take a reference to prevent skb_orphan() from freeing the socket */ + sock_hold(sk); + + err = sock_queue_err_skb(sk, skb); if (err) kfree_skb(skb); + + sock_put(sk); } EXPORT_SYMBOL_GPL(skb_complete_wifi_ack); @@ -4262,7 +4251,6 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet) if (!xnet) return; - ipvs_reset(skb); skb_orphan(skb); skb->mark = 0; } @@ -4302,18 +4290,13 @@ EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb) { - int mac_len; - if (skb_cow(skb, skb_headroom(skb)) < 0) { kfree_skb(skb); return NULL; } - mac_len = skb->data - skb_mac_header(skb); - if (likely(mac_len > VLAN_HLEN + ETH_TLEN)) { - memmove(skb_mac_header(skb) + VLAN_HLEN, skb_mac_header(skb), - mac_len - VLAN_HLEN - ETH_TLEN); - } + memmove(skb->data - ETH_HLEN, skb->data - skb->mac_len - VLAN_HLEN, + 2 * ETH_ALEN); skb->mac_header += VLAN_HLEN; return skb; } diff --git a/net/core/sock.c b/net/core/sock.c index 5436d130b1cf..09855fa7cdf0 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1567,11 +1567,6 @@ void sk_destruct(struct sock *sk) pr_debug("%s: optmem leakage (%d bytes) detected\n", __func__, atomic_read(&sk->sk_omem_alloc)); - if (sk->sk_frag.page) { - put_page(sk->sk_frag.page); - sk->sk_frag.page = NULL; - } - if (sk->sk_peer_cred) put_cred(sk->sk_peer_cred); put_pid(sk->sk_peer_pid); @@ -1582,7 +1577,7 @@ void sk_destruct(struct sock *sk) static void __sk_free(struct sock *sk) { - if (unlikely(sk->sk_net_refcnt && sock_diag_has_destroy_listeners(sk))) + if (unlikely(sock_diag_has_destroy_listeners(sk) && sk->sk_net_refcnt)) sock_diag_broadcast_destroy(sk); else sk_destruct(sk); @@ -1624,8 +1619,6 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) sock_copy(newsk, sk); - newsk->sk_prot_creator = sk->sk_prot; - /* SANITY */ if (likely(newsk->sk_net_refcnt)) get_net(sock_net(newsk)); @@ -1670,12 +1663,6 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) is_charged = sk_filter_charge(newsk, filter); if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk, sk))) { - /* We need to make sure that we don't uncharge the new - * socket if we couldn't charge it in the first place - * as otherwise we uncharge the parent's filter. - */ - if (!is_charged) - RCU_INIT_POINTER(newsk->sk_filter, NULL); /* It is still raw copy of parent, so invalidate * destructor and make plain sk_free() */ newsk->sk_destruct = NULL; @@ -1686,7 +1673,6 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) } newsk->sk_err = 0; - newsk->sk_err_soft = 0; newsk->sk_priority = 0; newsk->sk_incoming_cpu = raw_smp_processor_id(); atomic64_set(&newsk->sk_cookie, 0); @@ -1803,17 +1789,17 @@ EXPORT_SYMBOL(skb_set_owner_w); void skb_orphan_partial(struct sk_buff *skb) { + /* TCP stack sets skb->ooo_okay based on sk_wmem_alloc, + * so we do not completely orphan skb, but transfert all + * accounted bytes but one, to avoid unexpected reorders. + */ if (skb->destructor == sock_wfree #ifdef CONFIG_INET || skb->destructor == tcp_wfree #endif ) { - struct sock *sk = skb->sk; - - if (atomic_inc_not_zero(&sk->sk_refcnt)) { - atomic_sub(skb->truesize, &sk->sk_wmem_alloc); - skb->destructor = sock_efree; - } + atomic_sub(skb->truesize - 1, &skb->sk->sk_wmem_alloc); + skb->truesize = 1; } else { skb_orphan(skb); } @@ -2818,6 +2804,11 @@ void sk_common_release(struct sock *sk) sk_refcnt_debug_release(sk); + if (sk->sk_frag.page) { + put_page(sk->sk_frag.page); + sk->sk_frag.page = NULL; + } + sock_put(sk); } EXPORT_SYMBOL(sk_common_release); diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index 9653798da293..3963c3872c69 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -294,7 +294,7 @@ static int sock_diag_bind(struct net *net, int group) case SKNLGRP_INET6_UDP_DESTROY: if (!sock_diag_handlers[AF_INET6]) request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, - NETLINK_SOCK_DIAG, AF_INET6); + NETLINK_SOCK_DIAG, AF_INET); break; } return 0; diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 32898247d8bf..a6beb7b6ae55 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -292,13 +292,7 @@ static struct ctl_table net_core_table[] = { .data = &bpf_jit_enable, .maxlen = sizeof(int), .mode = 0644, -#ifndef CONFIG_BPF_JIT_ALWAYS_ON .proc_handler = proc_dointvec -#else - .proc_handler = proc_dointvec_minmax, - .extra1 = &one, - .extra2 = &one, -#endif }, #endif { @@ -366,16 +360,14 @@ static struct ctl_table net_core_table[] = { .data = &sysctl_net_busy_poll, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, + .proc_handler = proc_dointvec }, { .procname = "busy_read", .data = &sysctl_net_busy_read, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, + .proc_handler = proc_dointvec }, #endif #ifdef CONFIG_NET_SCHED @@ -429,6 +421,8 @@ static __net_init int sysctl_core_net_init(struct net *net) { struct ctl_table *tbl; + net->core.sysctl_somaxconn = SOMAXCONN; + tbl = netns_core_table; if (!net_eq(net, &init_net)) { tbl = kmemdup(tbl, sizeof(netns_core_table), GFP_KERNEL); diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 161dfcf86126..f053198e730c 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -126,16 +126,6 @@ static void ccid2_change_l_seq_window(struct sock *sk, u64 val) DCCPF_SEQ_WMAX)); } -static void dccp_tasklet_schedule(struct sock *sk) -{ - struct tasklet_struct *t = &dccp_sk(sk)->dccps_xmitlet; - - if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) { - sock_hold(sk); - __tasklet_schedule(t); - } -} - static void ccid2_hc_tx_rto_expire(unsigned long data) { struct sock *sk = (struct sock *)data; @@ -150,9 +140,6 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) ccid2_pr_debug("RTO_EXPIRE\n"); - if (sk->sk_state == DCCP_CLOSED) - goto out; - /* back-off timer */ hc->tx_rto <<= 1; if (hc->tx_rto > DCCP_RTO_MAX) @@ -176,7 +163,7 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) /* if we were blocked before, we may now send cwnd=1 packet */ if (sender_was_blocked) - dccp_tasklet_schedule(sk); + tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); /* restart backed-off timer */ sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); out: @@ -228,16 +215,14 @@ static void ccid2_cwnd_restart(struct sock *sk, const u32 now) struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); u32 cwnd = hc->tx_cwnd, restart_cwnd, iwnd = rfc3390_bytes_to_packets(dccp_sk(sk)->dccps_mss_cache); - s32 delta = now - hc->tx_lsndtime; hc->tx_ssthresh = max(hc->tx_ssthresh, (cwnd >> 1) + (cwnd >> 2)); /* don't reduce cwnd below the initial window (IW) */ restart_cwnd = min(cwnd, iwnd); - - while ((delta -= hc->tx_rto) >= 0 && cwnd > restart_cwnd) - cwnd >>= 1; + cwnd >>= (now - hc->tx_lsndtime) / hc->tx_rto; hc->tx_cwnd = max(cwnd, restart_cwnd); + hc->tx_cwnd_stamp = now; hc->tx_cwnd_used = 0; @@ -718,7 +703,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) done: /* check if incoming Acks allow pending packets to be sent */ if (sender_was_blocked && !ccid2_cwnd_network_limited(hc)) - dccp_tasklet_schedule(sk); + tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks); } @@ -764,7 +749,6 @@ static void ccid2_hc_tx_exit(struct sock *sk) for (i = 0; i < hc->tx_seqbufc; i++) kfree(hc->tx_seqbuf[i]); hc->tx_seqbufc = 0; - dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks); } static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 03fcf3ee1534..119c04317d48 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -599,7 +599,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk, { struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); struct dccp_sock *dp = dccp_sk(sk); - ktime_t now = ktime_get(); + ktime_t now = ktime_get_real(); s64 delta = 0; switch (fbtype) { @@ -624,14 +624,15 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk, case CCID3_FBACK_PERIODIC: delta = ktime_us_delta(now, hc->rx_tstamp_last_feedback); if (delta <= 0) - delta = 1; - hc->rx_x_recv = scaled_div32(hc->rx_bytes_recv, delta); + DCCP_BUG("delta (%ld) <= 0", (long)delta); + else + hc->rx_x_recv = scaled_div32(hc->rx_bytes_recv, delta); break; default: return; } - ccid3_pr_debug("Interval %lldusec, X_recv=%u, 1/p=%u\n", delta, + ccid3_pr_debug("Interval %ldusec, X_recv=%u, 1/p=%u\n", (long)delta, hc->rx_x_recv, hc->rx_pinv); hc->rx_tstamp_last_feedback = now; @@ -678,8 +679,7 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) static u32 ccid3_first_li(struct sock *sk) { struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); - u32 x_recv, p; - s64 delta; + u32 x_recv, p, delta; u64 fval; if (hc->rx_rtt == 0) { @@ -687,9 +687,7 @@ static u32 ccid3_first_li(struct sock *sk) hc->rx_rtt = DCCP_FALLBACK_RTT; } - delta = ktime_us_delta(ktime_get(), hc->rx_tstamp_last_feedback); - if (delta <= 0) - delta = 1; + delta = ktime_to_us(net_timedelta(hc->rx_tstamp_last_feedback)); x_recv = scaled_div32(hc->rx_bytes_recv, delta); if (x_recv == 0) { /* would also trigger divide-by-zero */ DCCP_WARN("X_recv==0\n"); diff --git a/net/dccp/feat.c b/net/dccp/feat.c index f227f002c73d..1704948e6a12 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -1471,12 +1471,9 @@ int dccp_feat_init(struct sock *sk) * singleton values (which always leads to failure). * These settings can still (later) be overridden via sockopts. */ - if (ccid_get_builtin_ccids(&tx.val, &tx.len)) + if (ccid_get_builtin_ccids(&tx.val, &tx.len) || + ccid_get_builtin_ccids(&rx.val, &rx.len)) return -ENOBUFS; - if (ccid_get_builtin_ccids(&rx.val, &rx.len)) { - kfree(tx.val); - return -ENOBUFS; - } if (!dccp_feat_prefer(sysctl_dccp_tx_ccid, tx.val, tx.len) || !dccp_feat_prefer(sysctl_dccp_rx_ccid, rx.val, rx.len)) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 45fd82e61e79..8be8f27bfacc 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -235,7 +235,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) { const struct iphdr *iph = (struct iphdr *)skb->data; const u8 offset = iph->ihl << 2; - const struct dccp_hdr *dh; + const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); struct dccp_sock *dp; struct inet_sock *inet; const int type = icmp_hdr(skb)->type; @@ -245,13 +245,11 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) int err; struct net *net = dev_net(skb->dev); - /* Only need dccph_dport & dccph_sport which are the first - * 4 bytes in dccp header. - * Our caller (icmp_socket_deliver()) already pulled 8 bytes for us. - */ - BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_sport) > 8); - BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_dport) > 8); - dh = (struct dccp_hdr *)(skb->data + offset); + if (skb->len < offset + sizeof(*dh) || + skb->len < offset + __dccp_basic_hdr_len(dh)) { + ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); + return; + } sk = __inet_lookup_established(net, &dccp_hashinfo, iph->daddr, dh->dccph_dport, @@ -289,8 +287,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) switch (type) { case ICMP_REDIRECT: - if (!sock_owned_by_user(sk)) - dccp_do_redirect(skb, sk); + dccp_do_redirect(skb, sk); goto out; case ICMP_SOURCE_QUENCH: /* Just silently ignore these. */ @@ -414,7 +411,8 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk, sk_daddr_set(newsk, ireq->ir_rmt_addr); sk_rcv_saddr_set(newsk, ireq->ir_loc_addr); newinet->inet_saddr = ireq->ir_loc_addr; - RCU_INIT_POINTER(newinet->inet_opt, rcu_dereference(ireq->ireq_opt)); + newinet->inet_opt = ireq->opt; + ireq->opt = NULL; newinet->mc_index = inet_iif(skb); newinet->mc_ttl = ip_hdr(skb)->ttl; newinet->inet_id = jiffies; @@ -429,10 +427,7 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk, if (__inet_inherit_port(sk, newsk) < 0) goto put_and_exit; *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash)); - if (*own_req) - ireq->ireq_opt = NULL; - else - newinet->inet_opt = NULL; + return newsk; exit_overflow: @@ -443,7 +438,6 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk, NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; put_and_exit: - newinet->inet_opt = NULL; inet_csk_prepare_forced_close(newsk); dccp_done(newsk); goto exit; @@ -495,7 +489,7 @@ static int dccp_v4_send_response(const struct sock *sk, struct request_sock *req ireq->ir_rmt_addr); err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr, ireq->ir_rmt_addr, - ireq_opt_deref(ireq)); + ireq->opt); err = net_xmit_eval(err); } @@ -549,7 +543,7 @@ static void dccp_v4_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb) static void dccp_v4_reqsk_destructor(struct request_sock *req) { dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg); - kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1)); + kfree(inet_rsk(req)->opt); } void dccp_syn_ack_timeout(const struct request_sock *req) @@ -618,7 +612,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ireq = inet_rsk(req); sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr); sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr); - ireq->ir_mark = inet_request_mark(sk, skb); ireq->ireq_family = AF_INET; ireq->ir_iif = sk->sk_bound_dev_if; @@ -639,7 +632,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) goto drop_and_free; inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); - reqsk_put(req); return 0; drop_and_free: @@ -704,7 +696,6 @@ int dccp_invalid_packet(struct sk_buff *skb) { const struct dccp_hdr *dh; unsigned int cscov; - u8 dccph_doff; if (skb->pkt_type != PACKET_HOST) return 1; @@ -726,19 +717,18 @@ int dccp_invalid_packet(struct sk_buff *skb) /* * If P.Data Offset is too small for packet type, drop packet and return */ - dccph_doff = dh->dccph_doff; - if (dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) { - DCCP_WARN("P.Data Offset(%u) too small\n", dccph_doff); + if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) { + DCCP_WARN("P.Data Offset(%u) too small\n", dh->dccph_doff); return 1; } /* * If P.Data Offset is too too large for packet, drop packet and return */ - if (!pskb_may_pull(skb, dccph_doff * sizeof(u32))) { - DCCP_WARN("P.Data Offset(%u) too large\n", dccph_doff); + if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) { + DCCP_WARN("P.Data Offset(%u) too large\n", dh->dccph_doff); return 1; } - dh = dccp_hdr(skb); + /* * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet * has short sequence numbers), drop packet and return diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 0bf41faeffc4..8bb485c91d00 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -70,7 +70,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info) { const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data; - const struct dccp_hdr *dh; + const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); struct dccp_sock *dp; struct ipv6_pinfo *np; struct sock *sk; @@ -78,13 +78,12 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, __u64 seq; struct net *net = dev_net(skb->dev); - /* Only need dccph_dport & dccph_sport which are the first - * 4 bytes in dccp header. - * Our caller (icmpv6_notify()) already pulled 8 bytes for us. - */ - BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_sport) > 8); - BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_dport) > 8); - dh = (struct dccp_hdr *)(skb->data + offset); + if (skb->len < offset + sizeof(*dh) || + skb->len < offset + __dccp_basic_hdr_len(dh)) { + ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), + ICMP6_MIB_INERRORS); + return; + } sk = __inet6_lookup_established(net, &dccp_hashinfo, &hdr->daddr, dh->dccph_dport, @@ -122,12 +121,10 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, np = inet6_sk(sk); if (type == NDISC_REDIRECT) { - if (!sock_owned_by_user(sk)) { - struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie); + struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie); - if (dst) - dst->ops->redirect(dst, sk, skb); - } + if (dst) + dst->ops->redirect(dst, sk, skb); goto out; } @@ -345,7 +342,6 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr; ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr; ireq->ireq_family = AF_INET6; - ireq->ir_mark = inet_request_mark(sk, skb); if (ipv6_opt_accepted(sk, skb, IP6CB(skb)) || np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || @@ -377,7 +373,6 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) goto drop_and_free; inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); - reqsk_put(req); return 0; drop_and_free: @@ -958,7 +953,6 @@ static const struct inet_connection_sock_af_ops dccp_ipv6_mapped = { .getsockopt = ipv6_getsockopt, .addr2sockaddr = inet6_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in6), - .bind_conflict = inet6_csk_bind_conflict, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_ipv6_setsockopt, .compat_getsockopt = compat_ipv6_getsockopt, diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 68eed344b471..1994f8af646b 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -122,7 +122,6 @@ struct sock *dccp_create_openreq_child(const struct sock *sk, /* It is still raw copy of parent, so invalidate * destructor and make plain sk_free() */ newsk->sk_destruct = NULL; - bh_unlock_sock(newsk); sk_free(newsk); return NULL; } @@ -146,13 +145,6 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb, struct dccp_request_sock *dreq = dccp_rsk(req); bool own_req; - /* TCP/DCCP listeners became lockless. - * DCCP stores complex state in its request_sock, so we need - * a protection for them, now this code runs without being protected - * by the parent (listener) lock. - */ - spin_lock_bh(&dreq->dreq_lock); - /* Check for retransmitted REQUEST */ if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) { @@ -167,7 +159,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb, inet_rtx_syn_ack(sk, req); } /* Network Duplicate, discard packet */ - goto out; + return NULL; } DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; @@ -193,20 +185,20 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb, child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL, req, &own_req); - if (child) { - child = inet_csk_complete_hashdance(sk, child, req, own_req); - goto out; - } + if (!child) + goto listen_overflow; + + return inet_csk_complete_hashdance(sk, child, req, own_req); +listen_overflow: + dccp_pr_debug("listen_overflow!\n"); DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY; drop: if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET) req->rsk_ops->send_reset(sk, skb); inet_csk_reqsk_queue_drop(sk, req); -out: - spin_unlock_bh(&dreq->dreq_lock); - return child; + return NULL; } EXPORT_SYMBOL_GPL(dccp_check_req); @@ -257,7 +249,6 @@ int dccp_reqsk_init(struct request_sock *req, { struct dccp_request_sock *dreq = dccp_rsk(req); - spin_lock_init(&dreq->dreq_lock); inet_rsk(req)->ir_rmt_port = dccp_hdr(skb)->dccph_sport; inet_rsk(req)->ir_num = ntohs(dccp_hdr(skb)->dccph_dport); inet_rsk(req)->acked = 0; diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 936dab12f99f..41e65804ddf5 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -171,15 +170,6 @@ const char *dccp_packet_name(const int type) EXPORT_SYMBOL_GPL(dccp_packet_name); -static void dccp_sk_destruct(struct sock *sk) -{ - struct dccp_sock *dp = dccp_sk(sk); - - ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); - dp->dccps_hc_tx_ccid = NULL; - inet_sock_destruct(sk); -} - int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) { struct dccp_sock *dp = dccp_sk(sk); @@ -189,7 +179,6 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) icsk->icsk_syn_retries = sysctl_dccp_request_retries; sk->sk_state = DCCP_CLOSED; sk->sk_write_space = dccp_write_space; - sk->sk_destruct = dccp_sk_destruct; icsk->icsk_sync_mss = dccp_sync_mss; dp->dccps_mss_cache = 536; dp->dccps_rate_last = jiffies; @@ -212,7 +201,10 @@ void dccp_destroy_sock(struct sock *sk) { struct dccp_sock *dp = dccp_sk(sk); - __skb_queue_purge(&sk->sk_write_queue); + /* + * DCCP doesn't use sk_write_queue, just sk_send_head + * for retransmissions + */ if (sk->sk_send_head != NULL) { kfree_skb(sk->sk_send_head); sk->sk_send_head = NULL; @@ -230,7 +222,8 @@ void dccp_destroy_sock(struct sock *sk) dp->dccps_hc_rx_ackvec = NULL; } ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); - dp->dccps_hc_rx_ccid = NULL; + ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); + dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; /* clean up feature negotiation state */ dccp_feat_list_purge(&dp->dccps_featneg); @@ -259,7 +252,6 @@ int dccp_disconnect(struct sock *sk, int flags) { struct inet_connection_sock *icsk = inet_csk(sk); struct inet_sock *inet = inet_sk(sk); - struct dccp_sock *dp = dccp_sk(sk); int err = 0; const int old_state = sk->sk_state; @@ -279,8 +271,6 @@ int dccp_disconnect(struct sock *sk, int flags) sk->sk_err = ECONNRESET; dccp_clear_xmit_timers(sk); - ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); - dp->dccps_hc_rx_ccid = NULL; __skb_queue_purge(&sk->sk_receive_queue); __skb_queue_purge(&sk->sk_write_queue); @@ -787,11 +777,6 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) if (skb == NULL) goto out_release; - if (sk->sk_state == DCCP_CLOSED) { - rc = -ENOTCONN; - goto out_discard; - } - skb_reserve(skb, sk->sk_prot->max_header); rc = memcpy_from_msg(skb_put(skb, len), msg, len); if (rc != 0) @@ -1024,10 +1009,6 @@ void dccp_close(struct sock *sk, long timeout) __kfree_skb(skb); } - /* If socket has been already reset kill it. */ - if (sk->sk_state == DCCP_CLOSED) - goto adjudge_to_death; - if (data_was_unread) { /* Unread data was tossed, send an appropriate Reset Code */ DCCP_WARN("ABORT with %u bytes unread\n", data_was_unread); diff --git a/net/dccp/timer.c b/net/dccp/timer.c index aa7c7dad7f96..3ef7acef3ce8 100644 --- a/net/dccp/timer.c +++ b/net/dccp/timer.c @@ -230,12 +230,12 @@ static void dccp_write_xmitlet(unsigned long data) else dccp_write_xmit(sk); bh_unlock_sock(sk); - sock_put(sk); } static void dccp_write_xmit_timer(unsigned long data) { dccp_write_xmitlet(data); + sock_put((struct sock *)data); } void dccp_init_xmit_timers(struct sock *sk) diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 9d8fcdefefc0..13d6b1a6e0fc 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -1337,12 +1337,6 @@ static int dn_setsockopt(struct socket *sock, int level, int optname, char __use lock_sock(sk); err = __dn_setsockopt(sock, level, optname, optval, optlen, 0); release_sock(sk); -#ifdef CONFIG_NETFILTER - /* we need to exclude all possible ENOPROTOOPTs except default case */ - if (err == -ENOPROTOOPT && optname != DSO_LINKINFO && - optname != DSO_STREAM && optname != DSO_SEQPACKET) - err = nf_setsockopt(sk, PF_DECnet, optname, optval, optlen); -#endif return err; } @@ -1450,6 +1444,15 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us dn_nsp_send_disc(sk, 0x38, 0, sk->sk_allocation); break; + default: +#ifdef CONFIG_NETFILTER + return nf_setsockopt(sk, PF_DECnet, optname, optval, optlen); +#endif + case DSO_LINKINFO: + case DSO_STREAM: + case DSO_SEQPACKET: + return -ENOPROTOOPT; + case DSO_MAXWINDOW: if (optlen != sizeof(unsigned long)) return -EINVAL; @@ -1497,12 +1500,6 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us return -EINVAL; scp->info_loc = u.info; break; - - case DSO_LINKINFO: - case DSO_STREAM: - case DSO_SEQPACKET: - default: - return -ENOPROTOOPT; } return 0; @@ -1516,20 +1513,6 @@ static int dn_getsockopt(struct socket *sock, int level, int optname, char __use lock_sock(sk); err = __dn_getsockopt(sock, level, optname, optval, optlen, 0); release_sock(sk); -#ifdef CONFIG_NETFILTER - if (err == -ENOPROTOOPT && optname != DSO_STREAM && - optname != DSO_SEQPACKET && optname != DSO_CONACCEPT && - optname != DSO_CONREJECT) { - int len; - - if (get_user(len, optlen)) - return -EFAULT; - - err = nf_getsockopt(sk, PF_DECnet, optname, optval, &len); - if (err >= 0) - err = put_user(len, optlen); - } -#endif return err; } @@ -1595,6 +1578,26 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us r_data = &link; break; + default: +#ifdef CONFIG_NETFILTER + { + int ret, len; + + if (get_user(len, optlen)) + return -EFAULT; + + ret = nf_getsockopt(sk, PF_DECnet, optname, optval, &len); + if (ret >= 0) + ret = put_user(len, optlen); + return ret; + } +#endif + case DSO_STREAM: + case DSO_SEQPACKET: + case DSO_CONACCEPT: + case DSO_CONREJECT: + return -ENOPROTOOPT; + case DSO_MAXWINDOW: if (r_len > sizeof(unsigned long)) r_len = sizeof(unsigned long); @@ -1626,13 +1629,6 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us r_len = sizeof(unsigned char); r_data = &scp->info_rem; break; - - case DSO_STREAM: - case DSO_SEQPACKET: - case DSO_CONACCEPT: - case DSO_CONREJECT: - default: - return -ENOPROTOOPT; } if (r_data) { diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 403593bd2b83..b1dc096d22f8 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -188,6 +188,12 @@ static inline void dnrt_free(struct dn_route *rt) call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); } +static inline void dnrt_drop(struct dn_route *rt) +{ + dst_release(&rt->dst); + call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); +} + static void dn_dst_check_expire(unsigned long dummy) { int i; @@ -242,7 +248,7 @@ static int dn_dst_gc(struct dst_ops *ops) } *rtp = rt->dst.dn_next; rt->dst.dn_next = NULL; - dnrt_free(rt); + dnrt_drop(rt); break; } spin_unlock_bh(&dn_rt_hash_table[i].lock); @@ -344,7 +350,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou dst_use(&rth->dst, now); spin_unlock_bh(&dn_rt_hash_table[hash].lock); - dst_free(&rt->dst); + dnrt_drop(rt); *rp = rth; return 0; } @@ -374,7 +380,7 @@ static void dn_run_flush(unsigned long dummy) for(; rt; rt = next) { next = rcu_dereference_raw(rt->dst.dn_next); RCU_INIT_POINTER(rt->dst.dn_next, NULL); - dnrt_free(rt); + dst_free((struct dst_entry *)rt); } nothing_to_declare: @@ -1181,7 +1187,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o if (dev_out->flags & IFF_LOOPBACK) flags |= RTCF_LOCAL; - rt = dst_alloc(&dn_dst_ops, dev_out, 0, DST_OBSOLETE_NONE, DST_HOST); + rt = dst_alloc(&dn_dst_ops, dev_out, 1, DST_OBSOLETE_NONE, DST_HOST); if (rt == NULL) goto e_nobufs; diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c index 29246bc9a7b4..85f2fdc360c2 100644 --- a/net/decnet/netfilter/dn_rtmsg.c +++ b/net/decnet/netfilter/dn_rtmsg.c @@ -102,9 +102,7 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb) { struct nlmsghdr *nlh = nlmsg_hdr(skb); - if (skb->len < sizeof(*nlh) || - nlh->nlmsg_len < sizeof(*nlh) || - skb->len < nlh->nlmsg_len) + if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) return; if (!netlink_capable(skb, CAP_NET_ADMIN)) diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index 1689c7bdf1c9..c79b85eb4d4c 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -87,39 +86,35 @@ dns_resolver_preparse(struct key_preparsed_payload *prep) opt++; kdebug("options: '%s'", opt); do { - int opt_len, opt_nlen; const char *eq; - char optval[128]; + int opt_len, opt_nlen, opt_vlen, tmp; next_opt = memchr(opt, '#', end - opt) ?: end; opt_len = next_opt - opt; - if (opt_len <= 0 || opt_len > sizeof(optval)) { - pr_warn_ratelimited("Invalid option length (%d) for dns_resolver key\n", - opt_len); + if (!opt_len) { + printk(KERN_WARNING + "Empty option to dns_resolver key\n"); return -EINVAL; } - eq = memchr(opt, '=', opt_len); - if (eq) { - opt_nlen = eq - opt; - eq++; - memcpy(optval, eq, next_opt - eq); - optval[next_opt - eq] = '\0'; - } else { - opt_nlen = opt_len; - optval[0] = '\0'; - } + eq = memchr(opt, '=', opt_len) ?: end; + opt_nlen = eq - opt; + eq++; + opt_vlen = next_opt - eq; /* will be -1 if no value */ - kdebug("option '%*.*s' val '%s'", - opt_nlen, opt_nlen, opt, optval); + tmp = opt_vlen >= 0 ? opt_vlen : 0; + kdebug("option '%*.*s' val '%*.*s'", + opt_nlen, opt_nlen, opt, tmp, tmp, eq); /* see if it's an error number representing a DNS error * that's to be recorded as the result in this key */ if (opt_nlen == sizeof(DNS_ERRORNO_OPTION) - 1 && memcmp(opt, DNS_ERRORNO_OPTION, opt_nlen) == 0) { kdebug("dns error number option"); + if (opt_vlen <= 0) + goto bad_option_value; - ret = kstrtoul(optval, 10, &derrno); + ret = kstrtoul(eq, 10, &derrno); if (ret < 0) goto bad_option_value; @@ -132,8 +127,10 @@ dns_resolver_preparse(struct key_preparsed_payload *prep) } bad_option_value: - pr_warn_ratelimited("Option '%*.*s' to dns_resolver key: bad/missing value\n", - opt_nlen, opt_nlen, opt); + printk(KERN_WARNING + "Option '%*.*s' to dns_resolver key:" + " bad/missing value\n", + opt_nlen, opt_nlen, opt); return -EINVAL; } while (opt = next_opt + 1, opt < end); } @@ -227,7 +224,7 @@ static int dns_resolver_match_preparse(struct key_match_data *match_data) static void dns_resolver_describe(const struct key *key, struct seq_file *m) { seq_puts(m, key->description); - if (key_is_positive(key)) { + if (key_is_instantiated(key)) { int err = PTR_ERR(key->payload.data[dns_key_error]); if (err) diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index fc0c09e770e6..ff7736f7ff42 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -1,13 +1,12 @@ config HAVE_NET_DSA def_bool y - depends on INET && NETDEVICES && !S390 + depends on NETDEVICES && !S390 # Drivers must select NET_DSA and the appropriate tagging format config NET_DSA tristate "Distributed Switch Architecture" - depends on HAVE_NET_DSA - select NET_SWITCHDEV + depends on HAVE_NET_DSA && NET_SWITCHDEV select PHYLIB ---help--- Say Y if you want to enable support for the hardware switches supported diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 48b28a7ecc7a..7bc787b095c8 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1006,8 +1006,10 @@ static int dsa_slave_phy_connect(struct dsa_slave_priv *p, /* Use already configured phy mode */ if (p->phy_interface == PHY_INTERFACE_MODE_NA) p->phy_interface = p->phy->interface; - return phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, - p->phy_interface); + phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, + p->phy_interface); + + return 0; } static int dsa_slave_phy_setup(struct dsa_slave_priv *p, @@ -1099,11 +1101,6 @@ int dsa_slave_suspend(struct net_device *slave_dev) { struct dsa_slave_priv *p = netdev_priv(slave_dev); - if (!netif_running(slave_dev)) - return 0; - - netif_device_detach(slave_dev); - if (p->phy) { phy_stop(p->phy); p->old_pause = -1; @@ -1119,9 +1116,6 @@ int dsa_slave_resume(struct net_device *slave_dev) { struct dsa_slave_priv *p = netdev_priv(slave_dev); - if (!netif_running(slave_dev)) - return 0; - netif_device_attach(slave_dev); if (p->phy) { diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 52dcd414c2af..9e63f252a89e 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -353,7 +353,6 @@ void ether_setup(struct net_device *dev) dev->header_ops = ð_header_ops; dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; - dev->min_header_len = ETH_HLEN; dev->mtu = ETH_DATA_LEN; dev->addr_len = ETH_ALEN; dev->tx_queue_len = 1000; /* Ethernet wants good queues */ @@ -437,7 +436,7 @@ struct sk_buff **eth_gro_receive(struct sk_buff **head, skb_gro_pull(skb, sizeof(*eh)); skb_gro_postpull_rcsum(skb, eh, sizeof(*eh)); - pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); + pp = ptype->callbacks.gro_receive(head, skb); out_unlock: rcu_read_unlock(); diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c index e8b279443d37..20c49c724ba0 100644 --- a/net/ieee802154/6lowpan/core.c +++ b/net/ieee802154/6lowpan/core.c @@ -206,13 +206,9 @@ static inline void lowpan_netlink_fini(void) static int lowpan_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *ndev = netdev_notifier_info_to_dev(ptr); - struct wpan_dev *wpan_dev; + struct net_device *wdev = netdev_notifier_info_to_dev(ptr); - if (ndev->type != ARPHRD_IEEE802154) - return NOTIFY_DONE; - wpan_dev = ndev->ieee802154_ptr; - if (!wpan_dev) + if (wdev->type != ARPHRD_IEEE802154) goto out; switch (event) { @@ -221,8 +217,8 @@ static int lowpan_device_event(struct notifier_block *unused, * also delete possible lowpan interfaces which belongs * to the wpan interface. */ - if (wpan_dev->lowpan_dev) - lowpan_dellink(wpan_dev->lowpan_dev, NULL); + if (wdev->ieee802154_ptr->lowpan_dev) + lowpan_dellink(wdev->ieee802154_ptr->lowpan_dev, NULL); break; default: break; diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c index 12e8cf4bda9f..6b437e8760d3 100644 --- a/net/ieee802154/6lowpan/reassembly.c +++ b/net/ieee802154/6lowpan/reassembly.c @@ -580,14 +580,19 @@ static int __net_init lowpan_frags_init_net(struct net *net) { struct netns_ieee802154_lowpan *ieee802154_lowpan = net_ieee802154_lowpan(net); + int res; ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH; ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH; ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT; - inet_frags_init_net(&ieee802154_lowpan->frags); - - return lowpan_frags_ns_sysctl_register(net); + res = inet_frags_init_net(&ieee802154_lowpan->frags); + if (res) + return res; + res = lowpan_frags_ns_sysctl_register(net); + if (res) + inet_frags_uninit_net(&ieee802154_lowpan->frags); + return res; } static void __net_exit lowpan_frags_exit_net(struct net *net) diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c index 47b397264f24..a548be247e15 100644 --- a/net/ieee802154/socket.c +++ b/net/ieee802154/socket.c @@ -302,12 +302,12 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) skb->sk = sk; skb->protocol = htons(ETH_P_IEEE802154); + dev_put(dev); + err = dev_queue_xmit(skb); if (err > 0) err = net_xmit_errno(err); - dev_put(dev); - return err ?: size; out_skb: @@ -689,12 +689,12 @@ static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) skb->sk = sk; skb->protocol = htons(ETH_P_IEEE802154); + dev_put(dev); + err = dev_queue_xmit(skb); if (err > 0) err = net_xmit_errno(err); - dev_put(dev); - return err ?: size; out_skb: diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 2e1b690c8f8c..4b9fe5ed658d 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -186,7 +186,6 @@ config NET_IPGRE_DEMUX config NET_IP_TUNNEL tristate - select DST_CACHE default n config NET_IPGRE @@ -354,7 +353,6 @@ config INET_ESP select CRYPTO_CBC select CRYPTO_SHA1 select CRYPTO_DES - select CRYPTO_ECHAINIV ---help--- Support for IPsec ESP. diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index ced5199416f9..a0f413bbdb32 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1102,7 +1102,7 @@ static struct inet_protosw inetsw_array[] = .type = SOCK_DGRAM, .protocol = IPPROTO_ICMP, .prot = &ping_prot, - .ops = &inet_sockraw_ops, + .ops = &inet_dgram_ops, .flags = INET_PROTOSW_REUSE, }, @@ -1460,7 +1460,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, skb_gro_pull(skb, sizeof(*iph)); skb_set_transport_header(skb, skb_gro_offset(skb)); - pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + pp = ops->callbacks.gro_receive(head, skb); out_unlock: rcu_read_unlock(); @@ -1526,13 +1526,6 @@ static int inet_gro_complete(struct sk_buff *skb, int nhoff) return err; } -static int ipip_gro_complete(struct sk_buff *skb, int nhoff) -{ - skb->encapsulation = 1; - skb_shinfo(skb)->gso_type |= SKB_GSO_IPIP; - return inet_gro_complete(skb, nhoff); -} - int inet_ctl_sock_create(struct sock **sk, unsigned short family, unsigned short type, unsigned char protocol, struct net *net) @@ -1761,7 +1754,7 @@ static const struct net_offload ipip_offload = { .callbacks = { .gso_segment = inet_gso_segment, .gro_receive = ipip_gro_receive, - .gro_complete = ipip_gro_complete, + .gro_complete = inet_gro_complete, }, }; diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index e8f862358518..f2a71025a770 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -220,9 +220,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); sg_init_table(sg, nfrags + sglists); - err = skb_to_sgvec_nomark(skb, sg, 0, skb->len); - if (unlikely(err < 0)) - goto out_free; + skb_to_sgvec_nomark(skb, sg, 0, skb->len); if (x->props.flags & XFRM_STATE_ESN) { /* Attach seqhi sg right after packet payload */ @@ -272,9 +270,6 @@ static void ah_input_done(struct crypto_async_request *base, int err) int ihl = ip_hdrlen(skb); int ah_hlen = (ah->hdrlen + 2) << 2; - if (err) - goto out; - work_iph = AH_SKB_CB(skb)->tmp; auth_data = ah_tmp_auth(work_iph, ihl); icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len); @@ -395,9 +390,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) skb_push(skb, ihl); sg_init_table(sg, nfrags + sglists); - err = skb_to_sgvec_nomark(skb, sg, 0, skb->len); - if (unlikely(err < 0)) - goto out_free; + skb_to_sgvec_nomark(skb, sg, 0, skb->len); if (x->props.flags & XFRM_STATE_ESN) { /* Attach seqhi sg right after packet payload */ diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index bfa79831873f..59b3e0e8fd51 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -223,16 +223,11 @@ static bool arp_key_eq(const struct neighbour *neigh, const void *pkey) static int arp_constructor(struct neighbour *neigh) { - __be32 addr; + __be32 addr = *(__be32 *)neigh->primary_key; struct net_device *dev = neigh->dev; struct in_device *in_dev; struct neigh_parms *parms; - u32 inaddr_any = INADDR_ANY; - if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) - memcpy(neigh->primary_key, &inaddr_any, arp_tbl.key_len); - - addr = *(__be32 *)neigh->primary_key; rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); if (!in_dev) { @@ -437,7 +432,7 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev) /*unsigned long now; */ struct net *net = dev_net(dev); - rt = ip_route_output(net, sip, tip, 0, l3mdev_master_ifindex_rcu(dev)); + rt = ip_route_output(net, sip, tip, 0, 0); if (IS_ERR(rt)) return 1; if (rt->dst.dev != dev) { @@ -658,7 +653,6 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb) unsigned char *arp_ptr; struct rtable *rt; unsigned char *sha; - unsigned char *tha = NULL; __be32 sip, tip; u16 dev_type = dev->type; int addr_type; @@ -730,7 +724,6 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb) break; #endif default: - tha = arp_ptr; arp_ptr += dev->addr_len; } memcpy(&tip, arp_ptr, 4); @@ -841,18 +834,8 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb) It is possible, that this option should be enabled for some devices (strip is candidate) */ - is_garp = tip == sip && addr_type == RTN_UNICAST; - - /* Unsolicited ARP _replies_ also require target hwaddr to be - * the same as source. - */ - if (is_garp && arp->ar_op == htons(ARPOP_REPLY)) - is_garp = - /* IPv4 over IEEE 1394 doesn't provide target - * hardware address field in its ARP payload. - */ - tha && - !memcmp(tha, sha, dev->addr_len); + is_garp = arp->ar_op == htons(ARPOP_REQUEST) && tip == sip && + addr_type == RTN_UNICAST; if (!n && ((arp->ar_op == htons(ARPOP_REPLY) && @@ -1267,7 +1250,7 @@ void __init arp_init(void) /* * ax25 -> ASCII conversion */ -static void ax2asc2(ax25_address *a, char *buf) +static char *ax2asc2(ax25_address *a, char *buf) { char c, *s; int n; @@ -1289,10 +1272,10 @@ static void ax2asc2(ax25_address *a, char *buf) *s++ = n + '0'; *s++ = '\0'; - if (*buf == '\0' || *buf == '-') { - buf[0] = '*'; - buf[1] = '\0'; - } + if (*buf == '\0' || *buf == '-') + return "*"; + + return buf; } #endif /* CONFIG_AX25 */ @@ -1326,7 +1309,7 @@ static void arp_format_neigh_entry(struct seq_file *seq, } #endif sprintf(tbuf, "%pI4", n->primary_key); - seq_printf(seq, "%-16s 0x%-10x0x%-10x%-17s * %s\n", + seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n", tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name); read_unlock(&n->lock); } diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 5169b9b36b6a..bdb2a07ec363 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1593,17 +1593,9 @@ unsigned char *cipso_v4_optptr(const struct sk_buff *skb) int taglen; for (optlen = iph->ihl*4 - sizeof(struct iphdr); optlen > 0; ) { - switch (optptr[0]) { - case IPOPT_CIPSO: + if (optptr[0] == IPOPT_CIPSO) return optptr; - case IPOPT_END: - return NULL; - case IPOPT_NOOP: - taglen = 1; - break; - default: - taglen = optptr[1]; - } + taglen = optptr[1]; optlen -= taglen; optptr += taglen; } @@ -1665,10 +1657,6 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option) goto validate_return_locked; } - if (opt_iter + 1 == opt_len) { - err_offset = opt_iter; - goto validate_return_locked; - } tag_len = tag[1]; if (tag_len > (opt_len - opt_iter)) { err_offset = opt_iter + 1; @@ -2020,7 +2008,7 @@ int cipso_v4_req_setattr(struct request_sock *req, buf = NULL; req_inet = inet_rsk(req); - opt = xchg((__force struct ip_options_rcu **)&req_inet->ireq_opt, opt); + opt = xchg(&req_inet->opt, opt); if (opt) kfree_rcu(opt, rcu); @@ -2042,13 +2030,11 @@ int cipso_v4_req_setattr(struct request_sock *req, * values on failure. * */ -static int cipso_v4_delopt(struct ip_options_rcu __rcu **opt_ptr) +static int cipso_v4_delopt(struct ip_options_rcu **opt_ptr) { - struct ip_options_rcu *opt = rcu_dereference_protected(*opt_ptr, 1); int hdr_delta = 0; + struct ip_options_rcu *opt = *opt_ptr; - if (!opt || opt->opt.cipso == 0) - return 0; if (opt->opt.srr || opt->opt.rr || opt->opt.ts || opt->opt.router_alert) { u8 cipso_len; u8 cipso_off; @@ -2110,10 +2096,14 @@ static int cipso_v4_delopt(struct ip_options_rcu __rcu **opt_ptr) */ void cipso_v4_sock_delattr(struct sock *sk) { - struct inet_sock *sk_inet; int hdr_delta; + struct ip_options_rcu *opt; + struct inet_sock *sk_inet; sk_inet = inet_sk(sk); + opt = rcu_dereference_protected(sk_inet->inet_opt, 1); + if (!opt || opt->opt.cipso == 0) + return; hdr_delta = cipso_v4_delopt(&sk_inet->inet_opt); if (sk_inet->is_icsk && hdr_delta > 0) { @@ -2133,7 +2123,15 @@ void cipso_v4_sock_delattr(struct sock *sk) */ void cipso_v4_req_delattr(struct request_sock *req) { - cipso_v4_delopt(&inet_rsk(req)->ireq_opt); + struct ip_options_rcu *opt; + struct inet_request_sock *req_inet; + + req_inet = inet_rsk(req); + opt = req_inet->opt; + if (!opt || opt->opt.cipso == 0) + return; + + cipso_v4_delopt(&req_inet->opt); } /** diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 63f99e9a821b..0212591b0077 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1358,7 +1358,7 @@ static void inetdev_changename(struct net_device *dev, struct in_device *in_dev) static bool inetdev_valid_mtu(unsigned int mtu) { - return mtu >= IPV4_MIN_MTU; + return mtu >= 68; } static void inetdev_send_gratuitous_arp(struct net_device *dev, diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 3d8021d55336..477937465a20 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -23,11 +23,6 @@ struct esp_skb_cb { void *tmp; }; -struct esp_output_extra { - __be32 seqhi; - u32 esphoff; -}; - #define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0])) static u32 esp4_get_mtu(struct xfrm_state *x, int mtu); @@ -40,11 +35,11 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu); * * TODO: Use spare space in skb for this where possible. */ -static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int extralen) +static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqhilen) { unsigned int len; - len = extralen; + len = seqhilen; len += crypto_aead_ivsize(aead); @@ -62,16 +57,15 @@ static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int extralen) return kmalloc(len, GFP_ATOMIC); } -static inline void *esp_tmp_extra(void *tmp) +static inline __be32 *esp_tmp_seqhi(void *tmp) { - return PTR_ALIGN(tmp, __alignof__(struct esp_output_extra)); + return PTR_ALIGN((__be32 *)tmp, __alignof__(__be32)); } - -static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int extralen) +static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int seqhilen) { return crypto_aead_ivsize(aead) ? - PTR_ALIGN((u8 *)tmp + extralen, - crypto_aead_alignmask(aead) + 1) : tmp + extralen; + PTR_ALIGN((u8 *)tmp + seqhilen, + crypto_aead_alignmask(aead) + 1) : tmp + seqhilen; } static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv) @@ -105,7 +99,7 @@ static void esp_restore_header(struct sk_buff *skb, unsigned int offset) { struct ip_esp_hdr *esph = (void *)(skb->data + offset); void *tmp = ESP_SKB_CB(skb)->tmp; - __be32 *seqhi = esp_tmp_extra(tmp); + __be32 *seqhi = esp_tmp_seqhi(tmp); esph->seq_no = esph->spi; esph->spi = *seqhi; @@ -113,11 +107,7 @@ static void esp_restore_header(struct sk_buff *skb, unsigned int offset) static void esp_output_restore_header(struct sk_buff *skb) { - void *tmp = ESP_SKB_CB(skb)->tmp; - struct esp_output_extra *extra = esp_tmp_extra(tmp); - - esp_restore_header(skb, skb_transport_offset(skb) + extra->esphoff - - sizeof(__be32)); + esp_restore_header(skb, skb_transport_offset(skb) - sizeof(__be32)); } static void esp_output_done_esn(struct crypto_async_request *base, int err) @@ -131,7 +121,6 @@ static void esp_output_done_esn(struct crypto_async_request *base, int err) static int esp_output(struct xfrm_state *x, struct sk_buff *skb) { int err; - struct esp_output_extra *extra; struct ip_esp_hdr *esph; struct crypto_aead *aead; struct aead_request *req; @@ -148,7 +137,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) int tfclen; int nfrags; int assoclen; - int extralen; + int seqhilen; + __be32 *seqhi; __be64 seqno; /* skb is pure payload to encrypt */ @@ -176,21 +166,21 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) nfrags = err; assoclen = sizeof(*esph); - extralen = 0; + seqhilen = 0; if (x->props.flags & XFRM_STATE_ESN) { - extralen += sizeof(*extra); - assoclen += sizeof(__be32); + seqhilen += sizeof(__be32); + assoclen += seqhilen; } - tmp = esp_alloc_tmp(aead, nfrags, extralen); + tmp = esp_alloc_tmp(aead, nfrags, seqhilen); if (!tmp) { err = -ENOMEM; goto error; } - extra = esp_tmp_extra(tmp); - iv = esp_tmp_iv(aead, tmp, extralen); + seqhi = esp_tmp_seqhi(tmp); + iv = esp_tmp_iv(aead, tmp, seqhilen); req = esp_tmp_req(aead, iv); sg = esp_req_sg(aead, req); @@ -257,10 +247,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) * encryption. */ if ((x->props.flags & XFRM_STATE_ESN)) { - extra->esphoff = (unsigned char *)esph - - skb_transport_header(skb); - esph = (struct ip_esp_hdr *)((unsigned char *)esph - 4); - extra->seqhi = esph->spi; + esph = (void *)(skb_transport_header(skb) - sizeof(__be32)); + *seqhi = esph->spi; esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.hi); aead_request_set_callback(req, 0, esp_output_done_esn, skb); } @@ -268,11 +256,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) esph->spi = x->id.spi; sg_init_table(sg, nfrags); - err = skb_to_sgvec(skb, sg, - (unsigned char *)esph - skb->data, - assoclen + ivlen + clen + alen); - if (unlikely(err < 0)) - goto error; + skb_to_sgvec(skb, sg, + (unsigned char *)esph - skb->data, + assoclen + ivlen + clen + alen); + aead_request_set_crypt(req, sg, sg, ivlen + clen, iv); aead_request_set_ad(req, assoclen); @@ -458,7 +445,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) goto out; ESP_SKB_CB(skb)->tmp = tmp; - seqhi = esp_tmp_extra(tmp); + seqhi = esp_tmp_seqhi(tmp); iv = esp_tmp_iv(aead, tmp, seqhilen); req = esp_tmp_req(aead, iv); sg = esp_req_sg(aead, req); @@ -477,14 +464,12 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) esph = (void *)skb_push(skb, 4); *seqhi = esph->spi; esph->spi = esph->seq_no; - esph->seq_no = XFRM_SKB_CB(skb)->seq.input.hi; + esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.input.hi); aead_request_set_callback(req, 0, esp_input_done_esn, skb); } sg_init_table(sg, nfrags); - err = skb_to_sgvec(skb, sg, 0, skb->len); - if (unlikely(err < 0)) - goto out; + skb_to_sgvec(skb, sg, 0, skb->len); aead_request_set_crypt(req, sg, sg, elen + ivlen, iv); aead_request_set_ad(req, assoclen); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 249a89491353..98c754e61024 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -85,7 +85,7 @@ struct fib_table *fib_new_table(struct net *net, u32 id) if (tb) return tb; - if (id == RT_TABLE_LOCAL && !net->ipv4.fib_has_custom_rules) + if (id == RT_TABLE_LOCAL) alias = fib_new_table(net, RT_TABLE_MAIN); tb = fib_trie_table(id, alias); @@ -289,19 +289,18 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb) return ip_hdr(skb)->daddr; in_dev = __in_dev_get_rcu(dev); + BUG_ON(!in_dev); net = dev_net(dev); scope = RT_SCOPE_UNIVERSE; if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) { - bool vmark = in_dev && IN_DEV_SRC_VMARK(in_dev); struct flowi4 fl4 = { .flowi4_iif = LOOPBACK_IFINDEX, - .flowi4_oif = l3mdev_master_ifindex_rcu(dev), .daddr = ip_hdr(skb)->saddr, .flowi4_tos = RT_TOS(ip_hdr(skb)->tos), .flowi4_scope = scope, - .flowi4_mark = vmark ? skb->mark : 0, + .flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0, }; if (!fib_lookup(net, &fl4, &res, 0)) return FIB_RES_PREFSRC(net, res); @@ -759,7 +758,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) unsigned int e = 0, s_e; struct fib_table *tb; struct hlist_head *head; - int dumped = 0, err; + int dumped = 0; if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) && ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED) @@ -779,27 +778,20 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) if (dumped) memset(&cb->args[2], 0, sizeof(cb->args) - 2 * sizeof(cb->args[0])); - err = fib_table_dump(tb, skb, cb); - if (err < 0) { - if (likely(skb->len)) - goto out; - - goto out_err; - } + if (fib_table_dump(tb, skb, cb) < 0) + goto out; dumped = 1; next: e++; } } out: - err = skb->len; -out_err: rcu_read_unlock(); cb->args[1] = e; cb->args[0] = h; - return err; + return skb->len; } /* Prepare and feed intra-kernel routing request. @@ -1089,8 +1081,7 @@ static void nl_fib_input(struct sk_buff *skb) net = sock_net(skb->sk); nlh = nlmsg_hdr(skb); - if (skb->len < nlmsg_total_size(sizeof(*frn)) || - skb->len < nlh->nlmsg_len || + if (skb->len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len || nlmsg_len(nlh) < sizeof(*frn)) return; @@ -1254,7 +1245,7 @@ static int __net_init ip_fib_net_init(struct net *net) static void ip_fib_net_exit(struct net *net) { - int i; + unsigned int i; rtnl_lock(); #ifdef CONFIG_IP_MULTIPLE_TABLES @@ -1262,12 +1253,7 @@ static void ip_fib_net_exit(struct net *net) RCU_INIT_POINTER(net->ipv4.fib_main, NULL); RCU_INIT_POINTER(net->ipv4.fib_default, NULL); #endif - /* Destroy the tables in reverse order to guarantee that the - * local table, ID 255, is destroyed before the main table, ID - * 254. This is necessary as the local table may contain - * references to data contained in the main table. - */ - for (i = FIB_TABLE_HASHSZ - 1; i >= 0; i--) { + for (i = 0; i < FIB_TABLE_HASHSZ; i++) { struct hlist_head *head = &net->ipv4.fib_table_hash[i]; struct hlist_node *tmp; struct fib_table *tb; @@ -1326,14 +1312,13 @@ static struct pernet_operations fib_net_ops = { void __init ip_fib_init(void) { - fib_trie_init(); + rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL); + rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL); + rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL); register_pernet_subsys(&fib_net_ops); - register_netdevice_notifier(&fib_netdev_notifier); register_inetaddr_notifier(&fib_inetaddr_notifier); - rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL); - rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL); - rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL); + fib_trie_init(); } diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 03ebff3950d8..2b68418c7198 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -204,7 +204,6 @@ static void rt_fibinfo_free_cpus(struct rtable __rcu * __percpu *rtp) static void free_fib_info_rcu(struct rcu_head *head) { struct fib_info *fi = container_of(head, struct fib_info, rcu); - struct dst_metrics *m; change_nexthops(fi) { if (nexthop_nh->nh_dev) @@ -215,9 +214,8 @@ static void free_fib_info_rcu(struct rcu_head *head) rt_fibinfo_free(&nexthop_nh->nh_rth_input); } endfor_nexthops(fi); - m = fi->fib_metrics; - if (m != &dst_default_metrics && atomic_dec_and_test(&m->refcnt)) - kfree(m); + if (fi->fib_metrics != (u32 *) dst_default_metrics) + kfree(fi->fib_metrics); kfree(fi); } @@ -481,9 +479,6 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, if (!rtnh_ok(rtnh, remaining)) return -EINVAL; - if (rtnh->rtnh_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN)) - return -EINVAL; - nexthop_nh->nh_flags = (cfg->fc_flags & ~0xFF) | rtnh->rtnh_flags; nexthop_nh->nh_oif = rtnh->rtnh_ifindex; @@ -640,11 +635,6 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) fi->fib_nh, cfg)) return 1; } -#ifdef CONFIG_IP_ROUTE_CLASSID - if (cfg->fc_flow && - cfg->fc_flow != fi->fib_nh->nh_tclassid) - return 1; -#endif if ((!cfg->fc_oif || cfg->fc_oif == fi->fib_nh->nh_oif) && (!cfg->fc_gw || cfg->fc_gw == fi->fib_nh->nh_gw)) return 0; @@ -979,8 +969,6 @@ fib_convert_metrics(struct fib_info *fi, const struct fib_config *cfg) if (val == TCP_CA_UNSPEC) return -EINVAL; } else { - if (nla_len(nla) != sizeof(u32)) - return -EINVAL; val = nla_get_u32(nla); } if (type == RTAX_ADVMSS && val > 65535 - 40) @@ -991,11 +979,11 @@ fib_convert_metrics(struct fib_info *fi, const struct fib_config *cfg) val = 255; if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK)) return -EINVAL; - fi->fib_metrics->metrics[type - 1] = val; + fi->fib_metrics[type - 1] = val; } if (ecn_ca) - fi->fib_metrics->metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA; + fi->fib_metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA; return 0; } @@ -1015,9 +1003,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg) if (fib_props[cfg->fc_type].scope > cfg->fc_scope) goto err_inval; - if (cfg->fc_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN)) - goto err_inval; - #ifdef CONFIG_IP_ROUTE_MULTIPATH if (cfg->fc_mp) { nhs = fib_count_nexthops(cfg->fc_mp, cfg->fc_mp_len); @@ -1051,17 +1036,14 @@ struct fib_info *fib_create_info(struct fib_config *cfg) fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); if (!fi) goto failure; - if (cfg->fc_mx) { - fi->fib_metrics = kzalloc(sizeof(*fi->fib_metrics), GFP_KERNEL); - if (unlikely(!fi->fib_metrics)) { - kfree(fi); - return ERR_PTR(err); - } - atomic_set(&fi->fib_metrics->refcnt, 1); - } else { - fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics; - } fib_info_cnt++; + if (cfg->fc_mx) { + fi->fib_metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); + if (!fi->fib_metrics) + goto failure; + } else + fi->fib_metrics = (u32 *) dst_default_metrics; + fi->fib_net = net; fi->fib_protocol = cfg->fc_protocol; fi->fib_scope = cfg->fc_scope; @@ -1263,7 +1245,7 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event, if (fi->fib_priority && nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority)) goto nla_put_failure; - if (rtnetlink_put_metrics(skb, fi->fib_metrics->metrics) < 0) + if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) goto nla_put_failure; if (fi->fib_prefsrc && @@ -1289,9 +1271,8 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event, nla_put_u32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid)) goto nla_put_failure; #endif - if (fi->fib_nh->nh_lwtstate && - lwtunnel_fill_encap(skb, fi->fib_nh->nh_lwtstate) < 0) - goto nla_put_failure; + if (fi->fib_nh->nh_lwtstate) + lwtunnel_fill_encap(skb, fi->fib_nh->nh_lwtstate); } #ifdef CONFIG_IP_ROUTE_MULTIPATH if (fi->fib_nhs > 1) { @@ -1327,10 +1308,8 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event, nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid)) goto nla_put_failure; #endif - if (nh->nh_lwtstate && - lwtunnel_fill_encap(skb, nh->nh_lwtstate) < 0) - goto nla_put_failure; - + if (nh->nh_lwtstate) + lwtunnel_fill_encap(skb, nh->nh_lwtstate); /* length of rtnetlink header + attributes */ rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *) rtnh; } endfor_nexthops(fi); @@ -1603,13 +1582,8 @@ void fib_select_multipath(struct fib_result *res, int hash) void fib_select_path(struct net *net, struct fib_result *res, struct flowi4 *fl4, int mp_hash) { - bool oif_check; - - oif_check = (fl4->flowi4_oif == 0 || - fl4->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF); - #ifdef CONFIG_IP_ROUTE_MULTIPATH - if (res->fi->fib_nhs > 1 && oif_check) { + if (res->fi->fib_nhs > 1 && fl4->flowi4_oif == 0) { if (mp_hash < 0) mp_hash = get_hash_from_flowi4(fl4) >> 1; @@ -1619,7 +1593,7 @@ void fib_select_path(struct net *net, struct fib_result *res, #endif if (!res->prefixlen && res->table->tb_num_default > 1 && - res->type == RTN_UNICAST && oif_check) + res->type == RTN_UNICAST && !fl4->flowi4_oif) fib_select_default(fl4, res); if (!fl4->saddr) diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 5c598f99a500..744e5936c10d 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1906,8 +1906,6 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb, /* rcu_read_lock is hold by caller */ hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) { - int err; - if (i < s_i) { i++; continue; @@ -1918,14 +1916,17 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb, continue; } - err = fib_dump_info(skb, NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, RTM_NEWROUTE, - tb->tb_id, fa->fa_type, - xkey, KEYLENGTH - fa->fa_slen, - fa->fa_tos, fa->fa_info, NLM_F_MULTI); - if (err < 0) { + if (fib_dump_info(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, + RTM_NEWROUTE, + tb->tb_id, + fa->fa_type, + xkey, + KEYLENGTH - fa->fa_slen, + fa->fa_tos, + fa->fa_info, NLM_F_MULTI) < 0) { cb->args[4] = i; - return err; + return -1; } i++; } @@ -1947,13 +1948,10 @@ int fib_table_dump(struct fib_table *tb, struct sk_buff *skb, t_key key = cb->args[3]; while ((l = leaf_walk_rcu(&tp, key)) != NULL) { - int err; - - err = fn_trie_dump_leaf(l, tb, skb, cb); - if (err < 0) { + if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) { cb->args[3] = key; cb->args[2] = count; - return err; + return -1; } ++count; @@ -2455,22 +2453,29 @@ struct fib_route_iter { static struct key_vector *fib_route_get_idx(struct fib_route_iter *iter, loff_t pos) { + struct fib_table *tb = iter->main_tb; struct key_vector *l, **tp = &iter->tnode; + struct trie *t; t_key key; - /* use cached location of previously found key */ + /* use cache location of next-to-find key */ if (iter->pos > 0 && pos >= iter->pos) { + pos -= iter->pos; key = iter->key; } else { - iter->pos = 1; + t = (struct trie *)tb->tb_data; + iter->tnode = t->kv; + iter->pos = 0; key = 0; } - pos -= iter->pos; - - while ((l = leaf_walk_rcu(tp, key)) && (pos-- > 0)) { + while ((l = leaf_walk_rcu(tp, key)) != NULL) { key = l->key + 1; iter->pos++; + + if (--pos <= 0) + break; + l = NULL; /* handle unlikely case of a key wrap */ @@ -2479,7 +2484,7 @@ static struct key_vector *fib_route_get_idx(struct fib_route_iter *iter, } if (l) - iter->key = l->key; /* remember it */ + iter->key = key; /* remember it */ else iter->pos = 0; /* forget it */ @@ -2500,14 +2505,14 @@ static void *fib_route_seq_start(struct seq_file *seq, loff_t *pos) return NULL; iter->main_tb = tb; - t = (struct trie *)tb->tb_data; - iter->tnode = t->kv; if (*pos != 0) return fib_route_get_idx(iter, *pos); + t = (struct trie *)tb->tb_data; + iter->tnode = t->kv; iter->pos = 0; - iter->key = KEY_MAX; + iter->key = 0; return SEQ_START_TOKEN; } @@ -2516,7 +2521,7 @@ static void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct fib_route_iter *iter = seq->private; struct key_vector *l = NULL; - t_key key = iter->key + 1; + t_key key = iter->key; ++*pos; @@ -2525,7 +2530,7 @@ static void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) l = leaf_walk_rcu(&iter->tnode, key); if (l) { - iter->key = l->key; + iter->key = l->key + 1; iter->pos++; } else { iter->pos = 0; diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 08d8ee124538..bd903fe0f750 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -48,7 +48,7 @@ static inline struct fou *fou_from_sock(struct sock *sk) return sk->sk_user_data; } -static int fou_recv_pull(struct sk_buff *skb, size_t len) +static void fou_recv_pull(struct sk_buff *skb, size_t len) { struct iphdr *iph = ip_hdr(skb); @@ -59,7 +59,6 @@ static int fou_recv_pull(struct sk_buff *skb, size_t len) __skb_pull(skb, len); skb_postpull_rcsum(skb, udp_hdr(skb), len); skb_reset_transport_header(skb); - return iptunnel_pull_offloads(skb); } static int fou_udp_recv(struct sock *sk, struct sk_buff *skb) @@ -69,14 +68,9 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb) if (!fou) return 1; - if (fou_recv_pull(skb, sizeof(struct udphdr))) - goto drop; + fou_recv_pull(skb, sizeof(struct udphdr)); return -fou->protocol; - -drop: - kfree_skb(skb); - return 0; } static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr, @@ -176,9 +170,6 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb) __skb_pull(skb, sizeof(struct udphdr) + hdrlen); skb_reset_transport_header(skb); - if (iptunnel_pull_offloads(skb)) - goto drop; - return -guehdr->proto_ctype; drop: @@ -201,7 +192,7 @@ static struct sk_buff **fou_gro_receive(struct sk_buff **head, if (!ops || !ops->callbacks.gro_receive) goto out_unlock; - pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + pp = ops->callbacks.gro_receive(head, skb); out_unlock: rcu_read_unlock(); @@ -360,7 +351,7 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head, if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive)) goto out_unlock; - pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + pp = ops->callbacks.gro_receive(head, skb); out_unlock: rcu_read_unlock(); diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 79ae0d7becbf..e603004c1af8 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c @@ -219,7 +219,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, /* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/ skb_gro_postpull_rcsum(skb, greh, grehlen); - pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); + pp = ptype->callbacks.gro_receive(head, skb); out_unlock: rcu_read_unlock(); diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index c67efa3e79dd..b3086cf27027 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -89,7 +89,6 @@ #include #include #include -#include #include #include @@ -226,14 +225,9 @@ static void igmp_start_timer(struct ip_mc_list *im, int max_delay) static void igmp_gq_start_timer(struct in_device *in_dev) { int tv = prandom_u32() % in_dev->mr_maxdelay; - unsigned long exp = jiffies + tv + 2; - - if (in_dev->mr_gq_running && - time_after_eq(exp, (in_dev->mr_gq_timer).expires)) - return; in_dev->mr_gq_running = 1; - if (!mod_timer(&in_dev->mr_gq_timer, exp)) + if (!mod_timer(&in_dev->mr_gq_timer, jiffies+tv+2)) in_dev_hold(in_dev); } @@ -328,23 +322,6 @@ igmp_scount(struct ip_mc_list *pmc, int type, int gdeleted, int sdeleted) return scount; } -/* source address selection per RFC 3376 section 4.2.13 */ -static __be32 igmpv3_get_srcaddr(struct net_device *dev, - const struct flowi4 *fl4) -{ - struct in_device *in_dev = __in_dev_get_rcu(dev); - - if (!in_dev) - return htonl(INADDR_ANY); - - for_ifa(in_dev) { - if (fl4->saddr == ifa->ifa_local) - return fl4->saddr; - } endfor_ifa(in_dev); - - return htonl(INADDR_ANY); -} - static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu) { struct sk_buff *skb; @@ -392,11 +369,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu) pip->frag_off = htons(IP_DF); pip->ttl = 1; pip->daddr = fl4.daddr; - - rcu_read_lock(); - pip->saddr = igmpv3_get_srcaddr(dev, &fl4); - rcu_read_unlock(); - + pip->saddr = fl4.saddr; pip->protocol = IPPROTO_IGMP; pip->tot_len = 0; /* filled in later */ ip_select_ident(net, skb, NULL); @@ -432,17 +405,16 @@ static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel) } static struct sk_buff *add_grhead(struct sk_buff *skb, struct ip_mc_list *pmc, - int type, struct igmpv3_grec **ppgr, unsigned int mtu) + int type, struct igmpv3_grec **ppgr) { struct net_device *dev = pmc->interface->dev; struct igmpv3_report *pih; struct igmpv3_grec *pgr; - if (!skb) { - skb = igmpv3_newpack(dev, mtu); - if (!skb) - return NULL; - } + if (!skb) + skb = igmpv3_newpack(dev, dev->mtu); + if (!skb) + return NULL; pgr = (struct igmpv3_grec *)skb_put(skb, sizeof(struct igmpv3_grec)); pgr->grec_type = type; pgr->grec_auxwords = 0; @@ -464,17 +436,12 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, struct igmpv3_grec *pgr = NULL; struct ip_sf_list *psf, *psf_next, *psf_prev, **psf_list; int scount, stotal, first, isquery, truncate; - unsigned int mtu; if (pmc->multiaddr == IGMP_ALL_HOSTS) return skb; if (ipv4_is_local_multicast(pmc->multiaddr) && !sysctl_igmp_llm_reports) return skb; - mtu = READ_ONCE(dev->mtu); - if (mtu < IPV4_MIN_MTU) - return skb; - isquery = type == IGMPV3_MODE_IS_INCLUDE || type == IGMPV3_MODE_IS_EXCLUDE; truncate = type == IGMPV3_MODE_IS_EXCLUDE || @@ -495,7 +462,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { if (skb) igmpv3_sendpack(skb); - skb = igmpv3_newpack(dev, mtu); + skb = igmpv3_newpack(dev, dev->mtu); } } first = 1; @@ -522,12 +489,12 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, pgr->grec_nsrcs = htons(scount); if (skb) igmpv3_sendpack(skb); - skb = igmpv3_newpack(dev, mtu); + skb = igmpv3_newpack(dev, dev->mtu); first = 1; scount = 0; } if (first) { - skb = add_grhead(skb, pmc, type, &pgr, mtu); + skb = add_grhead(skb, pmc, type, &pgr); first = 0; } if (!skb) @@ -561,7 +528,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, igmpv3_sendpack(skb); skb = NULL; /* add_grhead will get a new one */ } - skb = add_grhead(skb, pmc, type, &pgr, mtu); + skb = add_grhead(skb, pmc, type, &pgr); } } if (pgr) @@ -1130,7 +1097,6 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im) pmc = kzalloc(sizeof(*pmc), GFP_KERNEL); if (!pmc) return; - spin_lock_init(&pmc->lock); spin_lock_bh(&im->lock); pmc->interface = im->interface; in_dev_hold(in_dev); @@ -2055,26 +2021,21 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode, static void ip_mc_clear_src(struct ip_mc_list *pmc) { - struct ip_sf_list *psf, *nextpsf, *tomb, *sources; + struct ip_sf_list *psf, *nextpsf; - spin_lock_bh(&pmc->lock); - tomb = pmc->tomb; - pmc->tomb = NULL; - sources = pmc->sources; - pmc->sources = NULL; - pmc->sfmode = MCAST_EXCLUDE; - pmc->sfcount[MCAST_INCLUDE] = 0; - pmc->sfcount[MCAST_EXCLUDE] = 1; - spin_unlock_bh(&pmc->lock); - - for (psf = tomb; psf; psf = nextpsf) { + for (psf = pmc->tomb; psf; psf = nextpsf) { nextpsf = psf->sf_next; kfree(psf); } - for (psf = sources; psf; psf = nextpsf) { + pmc->tomb = NULL; + for (psf = pmc->sources; psf; psf = nextpsf) { nextpsf = psf->sf_next; kfree(psf); } + pmc->sources = NULL; + pmc->sfmode = MCAST_EXCLUDE; + pmc->sfcount[MCAST_INCLUDE] = 0; + pmc->sfcount[MCAST_EXCLUDE] = 1; } /* Join a multicast group diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index e2c66e5515cd..8aaacdc01d1e 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -415,11 +415,9 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk, { const struct inet_request_sock *ireq = inet_rsk(req); struct net *net = read_pnet(&ireq->ireq_net); - struct ip_options_rcu *opt; + struct ip_options_rcu *opt = ireq->opt; struct rtable *rt; - opt = ireq_opt_deref(ireq); - flowi4_init_output(fl4, ireq->ir_iif, ireq->ir_mark, RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, sk->sk_protocol, inet_sk_flowi_flags(sk), @@ -453,9 +451,10 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk, struct flowi4 *fl4; struct rtable *rt; - opt = rcu_dereference(ireq->ireq_opt); fl4 = &newinet->cork.fl.u.ip4; + rcu_read_lock(); + opt = rcu_dereference(newinet->inet_opt); flowi4_init_output(fl4, ireq->ir_iif, ireq->ir_mark, RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, sk->sk_protocol, inet_sk_flowi_flags(sk), @@ -468,11 +467,13 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk, goto no_route; if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway) goto route_err; + rcu_read_unlock(); return &rt->dst; route_err: ip_rt_put(rt); no_route: + rcu_read_unlock(); IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); return NULL; } diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index b2001b20e029..fe144dae7372 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -119,9 +119,6 @@ static void inet_frag_secret_rebuild(struct inet_frags *f) static bool inet_fragq_should_evict(const struct inet_frag_queue *q) { - if (!hlist_unhashed(&q->list_evictor)) - return false; - return q->net->low_thresh == 0 || frag_mem_limit(q->net) >= q->net->low_thresh; } @@ -237,8 +234,10 @@ void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f) cond_resched(); if (read_seqretry(&f->rnd_seqlock, seq) || - sum_frag_mem_limit(nf)) + percpu_counter_sum(&nf->mem)) goto evict_again; + + percpu_counter_destroy(&nf->mem); } EXPORT_SYMBOL(inet_frags_exit_net); @@ -364,6 +363,11 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, { struct inet_frag_queue *q; + if (frag_mem_limit(nf) > nf->high_thresh) { + inet_frag_schedule_worker(f); + return NULL; + } + q = kmem_cache_zalloc(f->frags_cachep, GFP_ATOMIC); if (!q) return NULL; @@ -400,11 +404,6 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, struct inet_frag_queue *q; int depth = 0; - if (!nf->high_thresh || frag_mem_limit(nf) > nf->high_thresh) { - inet_frag_schedule_worker(f); - return NULL; - } - if (frag_mem_limit(nf) > nf->low_thresh) inet_frag_schedule_worker(f); diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index d8316869947a..c67f9bd7699c 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -182,7 +182,6 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, tw->tw_dport = inet->inet_dport; tw->tw_family = sk->sk_family; tw->tw_reuse = sk->sk_reuse; - tw->tw_reuseport = sk->sk_reuseport; tw->tw_hash = sk->sk_hash; tw->tw_ipv6only = 0; tw->tw_transparent = inet->transparent; diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 7057a1b09b5e..b8a0607dab96 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -200,7 +200,6 @@ static void ip_expire(unsigned long arg) qp = container_of((struct inet_frag_queue *) arg, struct ipq, q); net = container_of(qp->q.net, struct net, ipv4.frags); - rcu_read_lock(); spin_lock(&qp->q.lock); if (qp->q.flags & INET_FRAG_COMPLETE) @@ -210,7 +209,7 @@ static void ip_expire(unsigned long arg) IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); if (!inet_frag_evicting(&qp->q)) { - struct sk_buff *clone, *head = qp->q.fragments; + struct sk_buff *head = qp->q.fragments; const struct iphdr *iph; int err; @@ -219,40 +218,32 @@ static void ip_expire(unsigned long arg) if (!(qp->q.flags & INET_FRAG_FIRST_IN) || !qp->q.fragments) goto out; + rcu_read_lock(); head->dev = dev_get_by_index_rcu(net, qp->iif); if (!head->dev) - goto out; - + goto out_rcu_unlock; /* skb has no dst, perform route lookup again */ iph = ip_hdr(head); err = ip_route_input_noref(head, iph->daddr, iph->saddr, iph->tos, head->dev); if (err) - goto out; + goto out_rcu_unlock; /* Only an end host needs to send an ICMP * "Fragment Reassembly Timeout" message, per RFC792. */ if (frag_expire_skip_icmp(qp->user) && (skb_rtable(head)->rt_type != RTN_LOCAL)) - goto out; - - clone = skb_clone(head, GFP_ATOMIC); + goto out_rcu_unlock; /* Send an ICMP "Fragment Reassembly Timeout" message. */ - if (clone) { - spin_unlock(&qp->q.lock); - icmp_send(clone, ICMP_TIME_EXCEEDED, - ICMP_EXC_FRAGTIME, 0); - consume_skb(clone); - goto out_rcu_unlock; - } + icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); +out_rcu_unlock: + rcu_read_unlock(); } out: spin_unlock(&qp->q.lock); -out_rcu_unlock: - rcu_read_unlock(); ipq_put(qp); } @@ -849,6 +840,8 @@ static void __init ip4_frags_ctl_register(void) static int __net_init ipv4_frags_init_net(struct net *net) { + int res; + /* Fragment cache limits. * * The fragment memory accounting code, (tries to) account for @@ -872,9 +865,13 @@ static int __net_init ipv4_frags_init_net(struct net *net) */ net->ipv4.frags.timeout = IP_FRAG_TIME; - inet_frags_init_net(&net->ipv4.frags); - - return ip4_frags_ns_ctl_register(net); + res = inet_frags_init_net(&net->ipv4.frags); + if (res) + return res; + res = ip4_frags_ns_ctl_register(net); + if (res) + inet_frags_uninit_net(&net->ipv4.frags); + return res; } static void __net_exit ipv4_frags_exit_net(struct net *net) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 3e4184088082..7dc962b89fa1 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1247,14 +1247,6 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name, err = ipgre_newlink(net, dev, tb, NULL); if (err < 0) goto out; - - /* openvswitch users expect packet sizes to be unrestricted, - * so set the largest MTU we can. - */ - err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); - if (err) - goto out; - return dev; out: free_netdev(dev); diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index cca310d10ffb..5df42e1a3f82 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -102,9 +102,6 @@ int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb) iph->tot_len = htons(skb->len); ip_send_check(iph); - - skb->protocol = htons(ETH_P_IP); - return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk, skb, NULL, skb_dst(skb)->dev, dst_output); @@ -480,8 +477,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->dev = from->dev; to->mark = from->mark; - skb_copy_hash(to, from); - /* Copy the flags to each fragment. */ IPCB(to)->flags = IPCB(from)->flags; @@ -925,7 +920,7 @@ static int __ip_append_data(struct sock *sk, cork->length += length; if ((skb && skb_is_gso(skb)) || - (((length + (skb ? skb->len : fragheaderlen)) > mtu) && + ((length > mtu) && (skb_queue_len(queue) <= 1) && (sk->sk_protocol == IPPROTO_UDP) && (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len && @@ -1064,8 +1059,7 @@ static int __ip_append_data(struct sock *sk, if (copy > length) copy = length; - if (!(rt->dst.dev->features&NETIF_F_SG) && - skb_tailroom(skb) >= copy) { + if (!(rt->dst.dev->features&NETIF_F_SG)) { unsigned int off; off = skb->len; diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 30f0a2c472e1..b84e31d54a53 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -101,17 +101,15 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb) } static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb, - int tlen, int offset) + int offset) { __wsum csum = skb->csum; if (skb->ip_summed != CHECKSUM_COMPLETE) return; - if (offset != 0) { - int tend_off = skb_transport_offset(skb) + tlen; - csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0)); - } + if (offset != 0) + csum = csum_sub(csum, csum_partial(skb->data, offset, 0)); put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum); } @@ -138,18 +136,15 @@ static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb) { struct sockaddr_in sin; const struct iphdr *iph = ip_hdr(skb); - __be16 *ports; - int end; + __be16 *ports = (__be16 *)skb_transport_header(skb); - end = skb_transport_offset(skb) + 4; - if (end > 0 && !pskb_may_pull(skb, end)) + if (skb_transport_offset(skb) + 4 > skb->len) return; /* All current transport protocols have the port numbers in the * first four bytes of the transport header and this function is * written with this assumption in mind. */ - ports = (__be16 *)skb_transport_header(skb); sin.sin_family = AF_INET; sin.sin_addr.s_addr = iph->daddr; @@ -160,7 +155,7 @@ static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb) } void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, - int tlen, int offset) + int offset) { struct inet_sock *inet = inet_sk(skb->sk); unsigned int flags = inet->cmsg_flags; @@ -223,7 +218,7 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, } if (flags & IP_CMSG_CHECKSUM) - ip_cmsg_recv_checksum(msg, skb, tlen, offset); + ip_cmsg_recv_checksum(msg, skb, offset); } EXPORT_SYMBOL(ip_cmsg_recv_offset); @@ -247,8 +242,7 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc, src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); if (!ipv6_addr_v4mapped(&src_info->ipi6_addr)) return -EINVAL; - if (src_info->ipi6_ifindex) - ipc->oif = src_info->ipi6_ifindex; + ipc->oif = src_info->ipi6_ifindex; ipc->addr = src_info->ipi6_addr.s6_addr32[3]; continue; } @@ -271,8 +265,7 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc, if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct in_pktinfo))) return -EINVAL; info = (struct in_pktinfo *)CMSG_DATA(cmsg); - if (info->ipi_ifindex) - ipc->oif = info->ipi_ifindex; + ipc->oif = info->ipi_ifindex; ipc->addr = info->ipi_spec_dst.s_addr; break; } @@ -499,6 +492,8 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) int err; int copied; + WARN_ON_ONCE(sk->sk_family == AF_INET6); + err = -EAGAIN; skb = sock_dequeue_err_skb(sk); if (!skb) @@ -827,7 +822,6 @@ static int do_ip_setsockopt(struct sock *sk, int level, { struct ip_mreqn mreq; struct net_device *dev = NULL; - int midx; if (sk->sk_type == SOCK_STREAM) goto e_inval; @@ -872,15 +866,11 @@ static int do_ip_setsockopt(struct sock *sk, int level, err = -EADDRNOTAVAIL; if (!dev) break; - - midx = l3mdev_master_ifindex(dev); - dev_put(dev); err = -EINVAL; if (sk->sk_bound_dev_if && - mreq.imr_ifindex != sk->sk_bound_dev_if && - (!midx || midx != sk->sk_bound_dev_if)) + mreq.imr_ifindex != sk->sk_bound_dev_if) break; inet->mc_index = mreq.imr_ifindex; @@ -1240,8 +1230,11 @@ int ip_setsockopt(struct sock *sk, int level, if (err == -ENOPROTOOPT && optname != IP_HDRINCL && optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY && - !ip_mroute_opt(optname)) + !ip_mroute_opt(optname)) { + lock_sock(sk); err = nf_setsockopt(sk, PF_INET, optname, optval, optlen); + release_sock(sk); + } #endif return err; } @@ -1266,9 +1259,12 @@ int compat_ip_setsockopt(struct sock *sk, int level, int optname, if (err == -ENOPROTOOPT && optname != IP_HDRINCL && optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY && - !ip_mroute_opt(optname)) - err = compat_nf_setsockopt(sk, PF_INET, optname, optval, - optlen); + !ip_mroute_opt(optname)) { + lock_sock(sk); + err = compat_nf_setsockopt(sk, PF_INET, optname, + optval, optlen); + release_sock(sk); + } #endif return err; } @@ -1546,7 +1542,10 @@ int ip_getsockopt(struct sock *sk, int level, if (get_user(len, optlen)) return -EFAULT; - err = nf_getsockopt(sk, PF_INET, optname, optval, &len); + lock_sock(sk); + err = nf_getsockopt(sk, PF_INET, optname, optval, + &len); + release_sock(sk); if (err >= 0) err = put_user(len, optlen); return err; @@ -1578,7 +1577,9 @@ int compat_ip_getsockopt(struct sock *sk, int level, int optname, if (get_user(len, optlen)) return -EFAULT; + lock_sock(sk); err = compat_nf_getsockopt(sk, PF_INET, optname, optval, &len); + release_sock(sk); if (err >= 0) err = put_user(len, optlen); return err; diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 3d62feb65932..ce30c8b72457 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -69,6 +69,61 @@ static unsigned int ip_tunnel_hash(__be32 key, __be32 remote) IP_TNL_HASH_BITS); } +static void __tunnel_dst_set(struct ip_tunnel_dst *idst, + struct dst_entry *dst, __be32 saddr) +{ + struct dst_entry *old_dst; + + dst_clone(dst); + old_dst = xchg((__force struct dst_entry **)&idst->dst, dst); + dst_release(old_dst); + idst->saddr = saddr; +} + +static noinline void tunnel_dst_set(struct ip_tunnel *t, + struct dst_entry *dst, __be32 saddr) +{ + __tunnel_dst_set(raw_cpu_ptr(t->dst_cache), dst, saddr); +} + +static void tunnel_dst_reset(struct ip_tunnel *t) +{ + tunnel_dst_set(t, NULL, 0); +} + +void ip_tunnel_dst_reset_all(struct ip_tunnel *t) +{ + int i; + + for_each_possible_cpu(i) + __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL, 0); +} +EXPORT_SYMBOL(ip_tunnel_dst_reset_all); + +static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, + u32 cookie, __be32 *saddr) +{ + struct ip_tunnel_dst *idst; + struct dst_entry *dst; + + rcu_read_lock(); + idst = raw_cpu_ptr(t->dst_cache); + dst = rcu_dereference(idst->dst); + if (dst && !atomic_inc_not_zero(&dst->__refcnt)) + dst = NULL; + if (dst) { + if (!dst->obsolete || dst->ops->check(dst, cookie)) { + *saddr = idst->saddr; + } else { + tunnel_dst_reset(t); + dst_release(dst); + dst = NULL; + } + } + rcu_read_unlock(); + return (struct rtable *)dst; +} + static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p, __be16 flags, __be32 key) { @@ -253,14 +308,13 @@ static struct net_device *__ip_tunnel_create(struct net *net, struct net_device *dev; char name[IFNAMSIZ]; - err = -E2BIG; - if (parms->name[0]) { - if (!dev_valid_name(parms->name)) - goto failed; + if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); - } else { - if (strlen(ops->kind) > (IFNAMSIZ - 3)) + else { + if (strlen(ops->kind) > (IFNAMSIZ - 3)) { + err = -E2BIG; goto failed; + } strlcpy(name, ops->kind, IFNAMSIZ); strncat(name, "%d", 2); } @@ -328,12 +382,11 @@ static int ip_tunnel_bind_dev(struct net_device *dev) if (!IS_ERR(rt)) { tdev = rt->dst.dev; + tunnel_dst_set(tunnel, &rt->dst, fl4.saddr); ip_rt_put(rt); } if (dev->type != ARPHRD_ETHER) dev->flags |= IFF_POINTOPOINT; - - dst_cache_reset(&tunnel->dst_cache); } if (!tdev && tunnel->parms.link) @@ -347,8 +400,8 @@ static int ip_tunnel_bind_dev(struct net_device *dev) dev->needed_headroom = t_hlen + hlen; mtu -= (dev->hard_header_len + t_hlen); - if (mtu < IPV4_MIN_MTU) - mtu = IPV4_MIN_MTU; + if (mtu < 68) + mtu = 68; return mtu; } @@ -680,8 +733,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) goto tx_error; - rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache, &fl4.saddr) : - NULL; + rt = connected ? tunnel_rtable_get(tunnel, 0, &fl4.saddr) : NULL; if (!rt) { rt = ip_route_output_key(tunnel->net, &fl4); @@ -691,8 +743,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, goto tx_error; } if (connected) - dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, - fl4.saddr); + tunnel_dst_set(tunnel, &rt->dst, fl4.saddr); } if (rt->dst.dev == dev) { @@ -790,7 +841,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn, if (set_mtu) dev->mtu = mtu; } - dst_cache_reset(&t->dst_cache); + ip_tunnel_dst_reset_all(t); netdev_state_change(dev); } @@ -897,31 +948,17 @@ int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) } EXPORT_SYMBOL_GPL(ip_tunnel_ioctl); -int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict) +int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) { struct ip_tunnel *tunnel = netdev_priv(dev); int t_hlen = tunnel->hlen + sizeof(struct iphdr); - int max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen; - if (new_mtu < 68) + if (new_mtu < 68 || + new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen) return -EINVAL; - - if (new_mtu > max_mtu) { - if (strict) - return -EINVAL; - - new_mtu = max_mtu; - } - dev->mtu = new_mtu; return 0; } -EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu); - -int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) -{ - return __ip_tunnel_change_mtu(dev, new_mtu, true); -} EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu); static void ip_tunnel_dev_free(struct net_device *dev) @@ -929,7 +966,7 @@ static void ip_tunnel_dev_free(struct net_device *dev) struct ip_tunnel *tunnel = netdev_priv(dev); gro_cells_destroy(&tunnel->gro_cells); - dst_cache_destroy(&tunnel->dst_cache); + free_percpu(tunnel->dst_cache); free_percpu(dev->tstats); free_netdev(dev); } @@ -1123,15 +1160,15 @@ int ip_tunnel_init(struct net_device *dev) if (!dev->tstats) return -ENOMEM; - err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); - if (err) { + tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); + if (!tunnel->dst_cache) { free_percpu(dev->tstats); - return err; + return -ENOMEM; } err = gro_cells_init(&tunnel->gro_cells, dev); if (err) { - dst_cache_destroy(&tunnel->dst_cache); + free_percpu(tunnel->dst_cache); free_percpu(dev->tstats); return err; } @@ -1161,7 +1198,7 @@ void ip_tunnel_uninit(struct net_device *dev) if (itn->fb_tunnel_dev != dev) ip_tunnel_del(itn, netdev_priv(dev)); - dst_cache_reset(&tunnel->dst_cache); + ip_tunnel_dst_reset_all(tunnel); } EXPORT_SYMBOL_GPL(ip_tunnel_uninit); diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index dbda0565781c..6cb9009c3d96 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -116,8 +116,7 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto) skb->vlan_tci = 0; skb_set_queue_mapping(skb, 0); skb->pkt_type = PACKET_HOST; - - return iptunnel_pull_offloads(skb); + return 0; } EXPORT_SYMBOL_GPL(iptunnel_pull_header); diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 4b7c81f88abf..4d8f0b698777 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -156,7 +156,6 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, struct ip_tunnel_parm *parms = &tunnel->parms; struct dst_entry *dst = skb_dst(skb); struct net_device *tdev; /* Device to other host */ - int pkt_len = skb->len; int err; if (!dst) { @@ -200,7 +199,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, err = dst_output(tunnel->net, skb->sk, skb); if (net_xmit_eval(err) == 0) - err = pkt_len; + err = skb->len; iptunnel_xmit_stats(err, &dev->stats, dev->tstats); return NETDEV_TX_OK; @@ -366,6 +365,7 @@ static int vti_tunnel_init(struct net_device *dev) memcpy(dev->dev_addr, &iph->saddr, 4); memcpy(dev->broadcast, &iph->daddr, 4); + dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); dev->mtu = ETH_DATA_LEN; dev->flags = IFF_NOARP; dev->addr_len = 4; @@ -540,33 +540,6 @@ static struct rtnl_link_ops vti_link_ops __read_mostly = { .get_link_net = ip_tunnel_get_link_net, }; -static bool is_vti_tunnel(const struct net_device *dev) -{ - return dev->netdev_ops == &vti_netdev_ops; -} - -static int vti_device_event(struct notifier_block *unused, - unsigned long event, void *ptr) -{ - struct net_device *dev = netdev_notifier_info_to_dev(ptr); - struct ip_tunnel *tunnel = netdev_priv(dev); - - if (!is_vti_tunnel(dev)) - return NOTIFY_DONE; - - switch (event) { - case NETDEV_DOWN: - if (!net_eq(tunnel->net, dev_net(dev))) - xfrm_garbage_collect(tunnel->net); - break; - } - return NOTIFY_DONE; -} - -static struct notifier_block vti_notifier_block __read_mostly = { - .notifier_call = vti_device_event, -}; - static int __init vti_init(void) { const char *msg; @@ -574,8 +547,6 @@ static int __init vti_init(void) pr_info("IPv4 over IPsec tunneling driver\n"); - register_netdevice_notifier(&vti_notifier_block); - msg = "tunnel device"; err = register_pernet_device(&vti_net_ops); if (err < 0) @@ -608,7 +579,6 @@ static int __init vti_init(void) xfrm_proto_esp_failed: unregister_pernet_device(&vti_net_ops); pernet_dev_failed: - unregister_netdevice_notifier(&vti_notifier_block); pr_err("vti init: failed to register %s\n", msg); return err; } @@ -620,7 +590,6 @@ static void __exit vti_fini(void) xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); unregister_pernet_device(&vti_net_ops); - unregister_netdevice_notifier(&vti_notifier_block); } module_init(vti_init); diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 60f564db25a3..0bc7412d9e14 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -152,11 +152,7 @@ static char dhcp_client_identifier[253] __initdata; /* Persistent data: */ -#ifdef IPCONFIG_DYNAMIC static int ic_proto_used; /* Protocol used, if any */ -#else -#define ic_proto_used 0 -#endif static __be32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */ static u8 ic_domain[64]; /* DNS (not NIS) domain name */ @@ -790,11 +786,6 @@ static void __init ic_bootp_init_ext(u8 *e) */ static inline void __init ic_bootp_init(void) { - /* Re-initialise all name servers to NONE, in case any were set via the - * "ip=" or "nfsaddrs=" kernel command line parameters: any IP addresses - * specified there will already have been decoded but are no longer - * needed - */ ic_nameservers_predef(); dev_add_pack(&bootp_packet_type); @@ -1428,13 +1419,6 @@ static int __init ip_auto_config(void) int err; unsigned int i; - /* Initialise all name servers to NONE (but only if the "ip=" or - * "nfsaddrs=" kernel command line parameters weren't decoded, otherwise - * we'll overwrite the IP addresses specified there) - */ - if (ic_set_manually == 0) - ic_nameservers_predef(); - #ifdef CONFIG_PROC_FS proc_create("pnp", S_IRUGO, init_net.proc_net, &pnp_seq_fops); #endif /* CONFIG_PROC_FS */ @@ -1652,7 +1636,6 @@ static int __init ip_auto_config_setup(char *addrs) return 1; } - /* Initialise all name servers to NONE */ ic_nameservers_predef(); /* Parse string for static IP assignment. */ diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 486b283a6cd1..a09fb0dec725 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -129,68 +129,42 @@ static struct rtnl_link_ops ipip_link_ops __read_mostly; static int ipip_err(struct sk_buff *skb, u32 info) { - /* All the routers (except for Linux) return only - 8 bytes of packet payload. It means, that precise relaying of - ICMP in the real Internet is absolutely infeasible. - */ +/* All the routers (except for Linux) return only + 8 bytes of packet payload. It means, that precise relaying of + ICMP in the real Internet is absolutely infeasible. + */ struct net *net = dev_net(skb->dev); struct ip_tunnel_net *itn = net_generic(net, ipip_net_id); const struct iphdr *iph = (const struct iphdr *)skb->data; + struct ip_tunnel *t; + int err; const int type = icmp_hdr(skb)->type; const int code = icmp_hdr(skb)->code; - struct ip_tunnel *t; - int err = 0; - - switch (type) { - case ICMP_DEST_UNREACH: - switch (code) { - case ICMP_SR_FAILED: - /* Impossible event. */ - goto out; - default: - /* All others are translated to HOST_UNREACH. - * rfc2003 contains "deep thoughts" about NET_UNREACH, - * I believe they are just ether pollution. --ANK - */ - break; - } - break; - - case ICMP_TIME_EXCEEDED: - if (code != ICMP_EXC_TTL) - goto out; - break; - - case ICMP_REDIRECT: - break; - - default: - goto out; - } + err = -ENOENT; t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, iph->daddr, iph->saddr, 0); - if (!t) { - err = -ENOENT; + if (!t) goto out; - } if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { - ipv4_update_pmtu(skb, net, info, t->parms.link, 0, - iph->protocol, 0); + ipv4_update_pmtu(skb, dev_net(skb->dev), info, + t->parms.link, 0, IPPROTO_IPIP, 0); + err = 0; goto out; } if (type == ICMP_REDIRECT) { - ipv4_redirect(skb, net, t->parms.link, 0, iph->protocol, 0); + ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0, + IPPROTO_IPIP, 0); + err = 0; goto out; } - if (t->parms.iph.daddr == 0) { - err = -ENOENT; + if (t->parms.iph.daddr == 0) goto out; - } + err = 0; if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) goto out; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8e77786549c6..c3a38353f5dc 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -882,10 +882,8 @@ static struct mfc_cache *ipmr_cache_alloc(void) { struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); - if (c) { - c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1; + if (c) c->mfc_un.res.minvif = MAXVIFS; - } return c; } @@ -2192,7 +2190,7 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, int ipmr_get_route(struct net *net, struct sk_buff *skb, __be32 saddr, __be32 daddr, - struct rtmsg *rtm, int nowait, u32 portid) + struct rtmsg *rtm, int nowait) { struct mfc_cache *cache; struct mr_table *mrt; @@ -2237,7 +2235,6 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb, return -ENOMEM; } - NETLINK_CB(skb2).portid = portid; skb_push(skb2, sizeof(struct iphdr)); skb_reset_network_header(skb2); iph = ip_hdr(skb2); diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 699f8a5457a3..c3776ff6749f 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -23,8 +23,7 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t struct rtable *rt; struct flowi4 fl4 = {}; __be32 saddr = iph->saddr; - const struct sock *sk = skb_to_full_sk(skb); - __u8 flags = sk ? inet_sk_flowi_flags(sk) : 0; + __u8 flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0; unsigned int hh_len; if (addr_type == RTN_UNSPEC) @@ -40,7 +39,7 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t fl4.daddr = iph->daddr; fl4.saddr = saddr; fl4.flowi4_tos = RT_TOS(iph->tos); - fl4.flowi4_oif = sk ? sk->sk_bound_dev_if : 0; + fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; fl4.flowi4_mark = skb->mark; fl4.flowi4_flags = flags; rt = ip_route_output_key(net, &fl4); @@ -59,7 +58,7 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t xfrm_decode_session(skb, flowi4_to_flowi(&fl4), AF_INET) == 0) { struct dst_entry *dst = skb_dst(skb); skb_dst_set(skb, NULL); - dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), sk, 0); + dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), skb->sk, 0); if (IS_ERR(dst)) return PTR_ERR(dst); skb_dst_set(skb, dst); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index f51b32ed353c..cf2ea1d2634a 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -375,8 +375,7 @@ static inline bool unconditional(const struct arpt_entry *e) * there are loops. Puts hook bitmask in comefrom. */ static int mark_source_chains(const struct xt_table_info *newinfo, - unsigned int valid_hooks, void *entry0, - unsigned int *offsets) + unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -444,8 +443,6 @@ static int mark_source_chains(const struct xt_table_info *newinfo, size = e->next_offset; e = (struct arpt_entry *) (entry0 + pos + size); - if (pos + size >= newinfo->size) - return 0; e->counters.pcnt = pos; pos += size; } else { @@ -465,16 +462,9 @@ static int mark_source_chains(const struct xt_table_info *newinfo, /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); - if (!xt_find_jump_offset(offsets, newpos, - newinfo->number)) - return 0; - e = (struct arpt_entry *) - (entry0 + newpos); } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; - if (newpos >= newinfo->size) - return 0; } e = (struct arpt_entry *) (entry0 + newpos); @@ -488,6 +478,25 @@ static int mark_source_chains(const struct xt_table_info *newinfo, return 1; } +static inline int check_entry(const struct arpt_entry *e, const char *name) +{ + const struct xt_entry_target *t; + + if (!arp_checkentry(&e->arp)) { + duprintf("arp_tables: arp check failed %p %s.\n", e, name); + return -EINVAL; + } + + if (e->target_offset + sizeof(struct xt_entry_target) > e->next_offset) + return -EINVAL; + + t = arpt_get_target_c(e); + if (e->target_offset + t->u.target_size > e->next_offset) + return -EINVAL; + + return 0; +} + static inline int check_target(struct arpt_entry *e, const char *name) { struct xt_entry_target *t = arpt_get_target(e); @@ -511,14 +520,18 @@ static inline int check_target(struct arpt_entry *e, const char *name) } static inline int -find_check_entry(struct arpt_entry *e, const char *name, unsigned int size, - struct xt_percpu_counter_alloc_state *alloc_state) +find_check_entry(struct arpt_entry *e, const char *name, unsigned int size) { struct xt_entry_target *t; struct xt_target *target; int ret; - if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) + ret = check_entry(e, name); + if (ret) + return ret; + + e->counters.pcnt = xt_percpu_counter_alloc(); + if (IS_ERR_VALUE(e->counters.pcnt)) return -ENOMEM; t = arpt_get_target(e); @@ -538,7 +551,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size, err: module_put(t->u.kernel.target->me); out: - xt_percpu_counter_free(&e->counters); + xt_percpu_counter_free(e->counters.pcnt); return ret; } @@ -567,11 +580,9 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, unsigned int valid_hooks) { unsigned int h; - int err; if ((unsigned long)e % __alignof__(struct arpt_entry) != 0 || - (unsigned char *)e + sizeof(struct arpt_entry) >= limit || - (unsigned char *)e + e->next_offset > limit) { + (unsigned char *)e + sizeof(struct arpt_entry) >= limit) { duprintf("Bad offset %p\n", e); return -EINVAL; } @@ -583,14 +594,6 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, return -EINVAL; } - if (!arp_checkentry(&e->arp)) - return -EINVAL; - - err = xt_check_entry_offsets(e, e->elems, e->target_offset, - e->next_offset); - if (err) - return err; - /* Check hooks & underflows */ for (h = 0; h < NF_ARP_NUMHOOKS; h++) { if (!(valid_hooks & (1 << h))) @@ -626,7 +629,7 @@ static inline void cleanup_entry(struct arpt_entry *e) if (par.target->destroy != NULL) par.target->destroy(&par); module_put(par.target->me); - xt_percpu_counter_free(&e->counters); + xt_percpu_counter_free(e->counters.pcnt); } /* Checks and translates the user-supplied table segment (held in @@ -635,9 +638,7 @@ static inline void cleanup_entry(struct arpt_entry *e) static int translate_table(struct xt_table_info *newinfo, void *entry0, const struct arpt_replace *repl) { - struct xt_percpu_counter_alloc_state alloc_state = { 0 }; struct arpt_entry *iter; - unsigned int *offsets; unsigned int i; int ret = 0; @@ -651,9 +652,6 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, } duprintf("translate_table: size %u\n", newinfo->size); - offsets = xt_alloc_entry_offsets(newinfo->number); - if (!offsets) - return -ENOMEM; i = 0; /* Walk through entries, checking offsets. */ @@ -664,9 +662,7 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, repl->underflow, repl->valid_hooks); if (ret != 0) - goto out_free; - if (i < repl->num_entries) - offsets[i] = (void *)iter - entry0; + break; ++i; if (strcmp(arpt_get_target(iter)->u.user.name, XT_ERROR_TARGET) == 0) @@ -674,13 +670,12 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, } duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); if (ret != 0) - goto out_free; + return ret; - ret = -EINVAL; if (i != repl->num_entries) { duprintf("translate_table: %u not %u entries\n", i, repl->num_entries); - goto out_free; + return -EINVAL; } /* Check hooks all assigned */ @@ -691,26 +686,24 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, if (newinfo->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", i, repl->hook_entry[i]); - goto out_free; + return -EINVAL; } if (newinfo->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", i, repl->underflow[i]); - goto out_free; + return -EINVAL; } } - if (!mark_source_chains(newinfo, repl->valid_hooks, entry0, offsets)) { - ret = -ELOOP; - goto out_free; + if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) { + duprintf("Looping hook\n"); + return -ELOOP; } - kvfree(offsets); /* Finally, each sanity check must pass */ i = 0; xt_entry_foreach(iter, entry0, newinfo->size) { - ret = find_check_entry(iter, repl->name, repl->size, - &alloc_state); + ret = find_check_entry(iter, repl->name, repl->size); if (ret != 0) break; ++i; @@ -725,9 +718,6 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, return ret; } - return ret; - out_free: - kvfree(offsets); return ret; } @@ -1139,17 +1129,55 @@ static int do_add_counters(struct net *net, const void __user *user, unsigned int i; struct xt_counters_info tmp; struct xt_counters *paddc; + unsigned int num_counters; + const char *name; + int size; + void *ptmp; struct xt_table *t; const struct xt_table_info *private; int ret = 0; struct arpt_entry *iter; unsigned int addend; +#ifdef CONFIG_COMPAT + struct compat_xt_counters_info compat_tmp; - paddc = xt_copy_counters_from_user(user, len, &tmp, compat); - if (IS_ERR(paddc)) - return PTR_ERR(paddc); + if (compat) { + ptmp = &compat_tmp; + size = sizeof(struct compat_xt_counters_info); + } else +#endif + { + ptmp = &tmp; + size = sizeof(struct xt_counters_info); + } - t = xt_find_table_lock(net, NFPROTO_ARP, tmp.name); + if (copy_from_user(ptmp, user, size) != 0) + return -EFAULT; + +#ifdef CONFIG_COMPAT + if (compat) { + num_counters = compat_tmp.num_counters; + name = compat_tmp.name; + } else +#endif + { + num_counters = tmp.num_counters; + name = tmp.name; + } + + if (len != size + num_counters * sizeof(struct xt_counters)) + return -EINVAL; + + paddc = vmalloc(len - size); + if (!paddc) + return -ENOMEM; + + if (copy_from_user(paddc, user + size, len - size) != 0) { + ret = -EFAULT; + goto free; + } + + t = xt_find_table_lock(net, NFPROTO_ARP, name); if (IS_ERR_OR_NULL(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; @@ -1157,7 +1185,7 @@ static int do_add_counters(struct net *net, const void __user *user, local_bh_disable(); private = t->private; - if (private->number != tmp.num_counters) { + if (private->number != num_counters) { ret = -EINVAL; goto unlock_up_free; } @@ -1184,18 +1212,6 @@ static int do_add_counters(struct net *net, const void __user *user, } #ifdef CONFIG_COMPAT -struct compat_arpt_replace { - char name[XT_TABLE_MAXNAMELEN]; - u32 valid_hooks; - u32 num_entries; - u32 size; - u32 hook_entry[NF_ARP_NUMHOOKS]; - u32 underflow[NF_ARP_NUMHOOKS]; - u32 num_counters; - compat_uptr_t counters; - struct compat_arpt_entry entries[0]; -}; - static inline void compat_release_entry(struct compat_arpt_entry *e) { struct xt_entry_target *t; @@ -1204,22 +1220,24 @@ static inline void compat_release_entry(struct compat_arpt_entry *e) module_put(t->u.kernel.target->me); } -static int +static inline int check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, struct xt_table_info *newinfo, unsigned int *size, const unsigned char *base, - const unsigned char *limit) + const unsigned char *limit, + const unsigned int *hook_entries, + const unsigned int *underflows, + const char *name) { struct xt_entry_target *t; struct xt_target *target; unsigned int entry_offset; - int ret, off; + int ret, off, h; duprintf("check_compat_entry_size_and_hooks %p\n", e); if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 || - (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit || - (unsigned char *)e + e->next_offset > limit) { + (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit) { duprintf("Bad offset %p, limit = %p\n", e, limit); return -EINVAL; } @@ -1231,11 +1249,8 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, return -EINVAL; } - if (!arp_checkentry(&e->arp)) - return -EINVAL; - - ret = xt_compat_check_entry_offsets(e, e->elems, e->target_offset, - e->next_offset); + /* For purposes of check_entry casting the compat entry is fine */ + ret = check_entry((struct arpt_entry *)e, name); if (ret) return ret; @@ -1259,6 +1274,17 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, if (ret) goto release_target; + /* Check hooks & underflows */ + for (h = 0; h < NF_ARP_NUMHOOKS; h++) { + if ((unsigned char *)e - base == hook_entries[h]) + newinfo->hook_entry[h] = hook_entries[h]; + if ((unsigned char *)e - base == underflows[h]) + newinfo->underflow[h] = underflows[h]; + } + + /* Clear counters and comefrom */ + memset(&e->counters, 0, sizeof(e->counters)); + e->comefrom = 0; return 0; release_target: @@ -1267,17 +1293,18 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, return ret; } -static void +static int compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, - unsigned int *size, + unsigned int *size, const char *name, struct xt_table_info *newinfo, unsigned char *base) { struct xt_entry_target *t; struct xt_target *target; struct arpt_entry *de; unsigned int origsize; - int h; + int ret, h; + ret = 0; origsize = *size; de = (struct arpt_entry *)*dstptr; memcpy(de, e, sizeof(struct arpt_entry)); @@ -1298,81 +1325,147 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, if ((unsigned char *)de - base < newinfo->underflow[h]) newinfo->underflow[h] -= origsize - *size; } + return ret; } -static int translate_compat_table(struct xt_table_info **pinfo, +static int translate_compat_table(const char *name, + unsigned int valid_hooks, + struct xt_table_info **pinfo, void **pentry0, - const struct compat_arpt_replace *compatr) + unsigned int total_size, + unsigned int number, + unsigned int *hook_entries, + unsigned int *underflows) { unsigned int i, j; struct xt_table_info *newinfo, *info; void *pos, *entry0, *entry1; struct compat_arpt_entry *iter0; - struct arpt_replace repl; + struct arpt_entry *iter1; unsigned int size; int ret = 0; info = *pinfo; entry0 = *pentry0; - size = compatr->size; - info->number = compatr->num_entries; + size = total_size; + info->number = number; + + /* Init all hooks to impossible value. */ + for (i = 0; i < NF_ARP_NUMHOOKS; i++) { + info->hook_entry[i] = 0xFFFFFFFF; + info->underflow[i] = 0xFFFFFFFF; + } duprintf("translate_compat_table: size %u\n", info->size); j = 0; xt_compat_lock(NFPROTO_ARP); - xt_compat_init_offsets(NFPROTO_ARP, compatr->num_entries); + xt_compat_init_offsets(NFPROTO_ARP, number); /* Walk through entries, checking offsets. */ - xt_entry_foreach(iter0, entry0, compatr->size) { + xt_entry_foreach(iter0, entry0, total_size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, - entry0 + compatr->size); + entry0 + total_size, + hook_entries, + underflows, + name); if (ret != 0) goto out_unlock; ++j; } ret = -EINVAL; - if (j != compatr->num_entries) { + if (j != number) { duprintf("translate_compat_table: %u not %u entries\n", - j, compatr->num_entries); + j, number); goto out_unlock; } + /* Check hooks all assigned */ + for (i = 0; i < NF_ARP_NUMHOOKS; i++) { + /* Only hooks which are valid */ + if (!(valid_hooks & (1 << i))) + continue; + if (info->hook_entry[i] == 0xFFFFFFFF) { + duprintf("Invalid hook entry %u %u\n", + i, hook_entries[i]); + goto out_unlock; + } + if (info->underflow[i] == 0xFFFFFFFF) { + duprintf("Invalid underflow %u %u\n", + i, underflows[i]); + goto out_unlock; + } + } + ret = -ENOMEM; newinfo = xt_alloc_table_info(size); if (!newinfo) goto out_unlock; - newinfo->number = compatr->num_entries; + newinfo->number = number; for (i = 0; i < NF_ARP_NUMHOOKS; i++) { - newinfo->hook_entry[i] = compatr->hook_entry[i]; - newinfo->underflow[i] = compatr->underflow[i]; + newinfo->hook_entry[i] = info->hook_entry[i]; + newinfo->underflow[i] = info->underflow[i]; } entry1 = newinfo->entries; pos = entry1; - size = compatr->size; - xt_entry_foreach(iter0, entry0, compatr->size) - compat_copy_entry_from_user(iter0, &pos, &size, - newinfo, entry1); - - /* all module references in entry0 are now gone */ - + size = total_size; + xt_entry_foreach(iter0, entry0, total_size) { + ret = compat_copy_entry_from_user(iter0, &pos, &size, + name, newinfo, entry1); + if (ret != 0) + break; + } xt_compat_flush_offsets(NFPROTO_ARP); xt_compat_unlock(NFPROTO_ARP); + if (ret) + goto free_newinfo; - memcpy(&repl, compatr, sizeof(*compatr)); + ret = -ELOOP; + if (!mark_source_chains(newinfo, valid_hooks, entry1)) + goto free_newinfo; - for (i = 0; i < NF_ARP_NUMHOOKS; i++) { - repl.hook_entry[i] = newinfo->hook_entry[i]; - repl.underflow[i] = newinfo->underflow[i]; - } + i = 0; + xt_entry_foreach(iter1, entry1, newinfo->size) { + iter1->counters.pcnt = xt_percpu_counter_alloc(); + if (IS_ERR_VALUE(iter1->counters.pcnt)) { + ret = -ENOMEM; + break; + } - repl.num_counters = 0; - repl.counters = NULL; - repl.size = newinfo->size; - ret = translate_table(newinfo, entry1, &repl); - if (ret) - goto free_newinfo; + ret = check_target(iter1, name); + if (ret != 0) { + xt_percpu_counter_free(iter1->counters.pcnt); + break; + } + ++i; + if (strcmp(arpt_get_target(iter1)->u.user.name, + XT_ERROR_TARGET) == 0) + ++newinfo->stacksize; + } + if (ret) { + /* + * The first i matches need cleanup_entry (calls ->destroy) + * because they had called ->check already. The other j-i + * entries need only release. + */ + int skip = i; + j -= i; + xt_entry_foreach(iter0, entry0, newinfo->size) { + if (skip-- > 0) + continue; + if (j-- == 0) + break; + compat_release_entry(iter0); + } + xt_entry_foreach(iter1, entry1, newinfo->size) { + if (i-- == 0) + break; + cleanup_entry(iter1); + } + xt_free_table_info(newinfo); + return ret; + } *pinfo = newinfo; *pentry0 = entry1; @@ -1381,18 +1474,31 @@ static int translate_compat_table(struct xt_table_info **pinfo, free_newinfo: xt_free_table_info(newinfo); - return ret; -out_unlock: - xt_compat_flush_offsets(NFPROTO_ARP); - xt_compat_unlock(NFPROTO_ARP); - xt_entry_foreach(iter0, entry0, compatr->size) { +out: + xt_entry_foreach(iter0, entry0, total_size) { if (j-- == 0) break; compat_release_entry(iter0); } return ret; +out_unlock: + xt_compat_flush_offsets(NFPROTO_ARP); + xt_compat_unlock(NFPROTO_ARP); + goto out; } +struct compat_arpt_replace { + char name[XT_TABLE_MAXNAMELEN]; + u32 valid_hooks; + u32 num_entries; + u32 size; + u32 hook_entry[NF_ARP_NUMHOOKS]; + u32 underflow[NF_ARP_NUMHOOKS]; + u32 num_counters; + compat_uptr_t counters; + struct compat_arpt_entry entries[0]; +}; + static int compat_do_replace(struct net *net, void __user *user, unsigned int len) { @@ -1425,7 +1531,10 @@ static int compat_do_replace(struct net *net, void __user *user, goto free_newinfo; } - ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp); + ret = translate_compat_table(tmp.name, tmp.valid_hooks, + &newinfo, &loc_cpu_entry, tmp.size, + tmp.num_entries, tmp.hook_entry, + tmp.underflow); if (ret != 0) goto free_newinfo; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2ff4eaad28c9..c3111d3c4930 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -452,8 +452,7 @@ ipt_do_table(struct sk_buff *skb, there are loops. Puts hook bitmask in comefrom. */ static int mark_source_chains(const struct xt_table_info *newinfo, - unsigned int valid_hooks, void *entry0, - unsigned int *offsets) + unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -526,8 +525,6 @@ mark_source_chains(const struct xt_table_info *newinfo, size = e->next_offset; e = (struct ipt_entry *) (entry0 + pos + size); - if (pos + size >= newinfo->size) - return 0; e->counters.pcnt = pos; pos += size; } else { @@ -546,16 +543,9 @@ mark_source_chains(const struct xt_table_info *newinfo, /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); - if (!xt_find_jump_offset(offsets, newpos, - newinfo->number)) - return 0; - e = (struct ipt_entry *) - (entry0 + newpos); } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; - if (newpos >= newinfo->size) - return 0; } e = (struct ipt_entry *) (entry0 + newpos); @@ -582,6 +572,27 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) module_put(par.match->me); } +static int +check_entry(const struct ipt_entry *e, const char *name) +{ + const struct xt_entry_target *t; + + if (!ip_checkentry(&e->ip)) { + duprintf("ip check failed %p %s.\n", e, name); + return -EINVAL; + } + + if (e->target_offset + sizeof(struct xt_entry_target) > + e->next_offset) + return -EINVAL; + + t = ipt_get_target_c(e); + if (e->target_offset + t->u.target_size > e->next_offset) + return -EINVAL; + + return 0; +} + static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) { @@ -650,8 +661,7 @@ static int check_target(struct ipt_entry *e, struct net *net, const char *name) static int find_check_entry(struct ipt_entry *e, struct net *net, const char *name, - unsigned int size, - struct xt_percpu_counter_alloc_state *alloc_state) + unsigned int size) { struct xt_entry_target *t; struct xt_target *target; @@ -660,11 +670,15 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, struct xt_mtchk_param mtpar; struct xt_entry_match *ematch; - if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) + ret = check_entry(e, name); + if (ret) + return ret; + + e->counters.pcnt = xt_percpu_counter_alloc(); + if (IS_ERR_VALUE(e->counters.pcnt)) return -ENOMEM; j = 0; - memset(&mtpar, 0, sizeof(mtpar)); mtpar.net = net; mtpar.table = name; mtpar.entryinfo = &e->ip; @@ -701,7 +715,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, cleanup_match(ematch, net); } - xt_percpu_counter_free(&e->counters); + xt_percpu_counter_free(e->counters.pcnt); return ret; } @@ -731,11 +745,9 @@ check_entry_size_and_hooks(struct ipt_entry *e, unsigned int valid_hooks) { unsigned int h; - int err; if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 || - (unsigned char *)e + sizeof(struct ipt_entry) >= limit || - (unsigned char *)e + e->next_offset > limit) { + (unsigned char *)e + sizeof(struct ipt_entry) >= limit) { duprintf("Bad offset %p\n", e); return -EINVAL; } @@ -747,14 +759,6 @@ check_entry_size_and_hooks(struct ipt_entry *e, return -EINVAL; } - if (!ip_checkentry(&e->ip)) - return -EINVAL; - - err = xt_check_entry_offsets(e, e->elems, e->target_offset, - e->next_offset); - if (err) - return err; - /* Check hooks & underflows */ for (h = 0; h < NF_INET_NUMHOOKS; h++) { if (!(valid_hooks & (1 << h))) @@ -797,7 +801,7 @@ cleanup_entry(struct ipt_entry *e, struct net *net) if (par.target->destroy != NULL) par.target->destroy(&par); module_put(par.target->me); - xt_percpu_counter_free(&e->counters); + xt_percpu_counter_free(e->counters.pcnt); } /* Checks and translates the user-supplied table segment (held in @@ -806,9 +810,7 @@ static int translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, const struct ipt_replace *repl) { - struct xt_percpu_counter_alloc_state alloc_state = { 0 }; struct ipt_entry *iter; - unsigned int *offsets; unsigned int i; int ret = 0; @@ -822,9 +824,6 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, } duprintf("translate_table: size %u\n", newinfo->size); - offsets = xt_alloc_entry_offsets(newinfo->number); - if (!offsets) - return -ENOMEM; i = 0; /* Walk through entries, checking offsets. */ @@ -834,10 +833,9 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, repl->hook_entry, repl->underflow, repl->valid_hooks); - if (ret != 0) - goto out_free; - if (i < repl->num_entries) - offsets[i] = (void *)iter - entry0; + if (ret != 0) { + return ret; + } ++i; if (strcmp(ipt_get_target(iter)->u.user.name, XT_ERROR_TARGET) == 0) { @@ -845,11 +843,10 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, } } - ret = -EINVAL; if (i != repl->num_entries) { duprintf("translate_table: %u not %u entries\n", i, repl->num_entries); - goto out_free; + return -EINVAL; } /* Check hooks all assigned */ @@ -860,26 +857,22 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, if (newinfo->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", i, repl->hook_entry[i]); - goto out_free; + return -EINVAL; } if (newinfo->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", i, repl->underflow[i]); - goto out_free; + return -EINVAL; } } - if (!mark_source_chains(newinfo, repl->valid_hooks, entry0, offsets)) { - ret = -ELOOP; - goto out_free; - } - kvfree(offsets); + if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) + return -ELOOP; /* Finally, each sanity check must pass */ i = 0; xt_entry_foreach(iter, entry0, newinfo->size) { - ret = find_check_entry(iter, net, repl->name, repl->size, - &alloc_state); + ret = find_check_entry(iter, net, repl->name, repl->size); if (ret != 0) break; ++i; @@ -894,9 +887,6 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, return ret; } - return ret; - out_free: - kvfree(offsets); return ret; } @@ -1326,17 +1316,55 @@ do_add_counters(struct net *net, const void __user *user, unsigned int i; struct xt_counters_info tmp; struct xt_counters *paddc; + unsigned int num_counters; + const char *name; + int size; + void *ptmp; struct xt_table *t; const struct xt_table_info *private; int ret = 0; struct ipt_entry *iter; unsigned int addend; +#ifdef CONFIG_COMPAT + struct compat_xt_counters_info compat_tmp; + + if (compat) { + ptmp = &compat_tmp; + size = sizeof(struct compat_xt_counters_info); + } else +#endif + { + ptmp = &tmp; + size = sizeof(struct xt_counters_info); + } + + if (copy_from_user(ptmp, user, size) != 0) + return -EFAULT; - paddc = xt_copy_counters_from_user(user, len, &tmp, compat); - if (IS_ERR(paddc)) - return PTR_ERR(paddc); +#ifdef CONFIG_COMPAT + if (compat) { + num_counters = compat_tmp.num_counters; + name = compat_tmp.name; + } else +#endif + { + num_counters = tmp.num_counters; + name = tmp.name; + } - t = xt_find_table_lock(net, AF_INET, tmp.name); + if (len != size + num_counters * sizeof(struct xt_counters)) + return -EINVAL; + + paddc = vmalloc(len - size); + if (!paddc) + return -ENOMEM; + + if (copy_from_user(paddc, user + size, len - size) != 0) { + ret = -EFAULT; + goto free; + } + + t = xt_find_table_lock(net, AF_INET, name); if (IS_ERR_OR_NULL(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; @@ -1344,7 +1372,7 @@ do_add_counters(struct net *net, const void __user *user, local_bh_disable(); private = t->private; - if (private->number != tmp.num_counters) { + if (private->number != num_counters) { ret = -EINVAL; goto unlock_up_free; } @@ -1423,6 +1451,7 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, static int compat_find_calc_match(struct xt_entry_match *m, + const char *name, const struct ipt_ip *ip, int *size) { @@ -1457,19 +1486,21 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, struct xt_table_info *newinfo, unsigned int *size, const unsigned char *base, - const unsigned char *limit) + const unsigned char *limit, + const unsigned int *hook_entries, + const unsigned int *underflows, + const char *name) { struct xt_entry_match *ematch; struct xt_entry_target *t; struct xt_target *target; unsigned int entry_offset; unsigned int j; - int ret, off; + int ret, off, h; duprintf("check_compat_entry_size_and_hooks %p\n", e); if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 || - (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit || - (unsigned char *)e + e->next_offset > limit) { + (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) { duprintf("Bad offset %p, limit = %p\n", e, limit); return -EINVAL; } @@ -1481,11 +1512,8 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, return -EINVAL; } - if (!ip_checkentry(&e->ip)) - return -EINVAL; - - ret = xt_compat_check_entry_offsets(e, e->elems, - e->target_offset, e->next_offset); + /* For purposes of check_entry casting the compat entry is fine */ + ret = check_entry((struct ipt_entry *)e, name); if (ret) return ret; @@ -1493,7 +1521,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, entry_offset = (void *)e - (void *)base; j = 0; xt_ematch_foreach(ematch, e) { - ret = compat_find_calc_match(ematch, &e->ip, &off); + ret = compat_find_calc_match(ematch, name, &e->ip, &off); if (ret != 0) goto release_matches; ++j; @@ -1516,6 +1544,17 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, if (ret) goto out; + /* Check hooks & underflows */ + for (h = 0; h < NF_INET_NUMHOOKS; h++) { + if ((unsigned char *)e - base == hook_entries[h]) + newinfo->hook_entry[h] = hook_entries[h]; + if ((unsigned char *)e - base == underflows[h]) + newinfo->underflow[h] = underflows[h]; + } + + /* Clear counters and comefrom */ + memset(&e->counters, 0, sizeof(e->counters)); + e->comefrom = 0; return 0; out: @@ -1529,18 +1568,19 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, return ret; } -static void +static int compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, - unsigned int *size, + unsigned int *size, const char *name, struct xt_table_info *newinfo, unsigned char *base) { struct xt_entry_target *t; struct xt_target *target; struct ipt_entry *de; unsigned int origsize; - int h; + int ret, h; struct xt_entry_match *ematch; + ret = 0; origsize = *size; de = (struct ipt_entry *)*dstptr; memcpy(de, e, sizeof(struct ipt_entry)); @@ -1549,104 +1589,200 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, *dstptr += sizeof(struct ipt_entry); *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); - xt_ematch_foreach(ematch, e) - xt_compat_match_from_user(ematch, dstptr, size); - + xt_ematch_foreach(ematch, e) { + ret = xt_compat_match_from_user(ematch, dstptr, size); + if (ret != 0) + return ret; + } de->target_offset = e->target_offset - (origsize - *size); t = compat_ipt_get_target(e); target = t->u.kernel.target; xt_compat_target_from_user(t, dstptr, size); de->next_offset = e->next_offset - (origsize - *size); - for (h = 0; h < NF_INET_NUMHOOKS; h++) { if ((unsigned char *)de - base < newinfo->hook_entry[h]) newinfo->hook_entry[h] -= origsize - *size; if ((unsigned char *)de - base < newinfo->underflow[h]) newinfo->underflow[h] -= origsize - *size; } + return ret; +} + +static int +compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) +{ + struct xt_entry_match *ematch; + struct xt_mtchk_param mtpar; + unsigned int j; + int ret = 0; + + e->counters.pcnt = xt_percpu_counter_alloc(); + if (IS_ERR_VALUE(e->counters.pcnt)) + return -ENOMEM; + + j = 0; + mtpar.net = net; + mtpar.table = name; + mtpar.entryinfo = &e->ip; + mtpar.hook_mask = e->comefrom; + mtpar.family = NFPROTO_IPV4; + xt_ematch_foreach(ematch, e) { + ret = check_match(ematch, &mtpar); + if (ret != 0) + goto cleanup_matches; + ++j; + } + + ret = check_target(e, net, name); + if (ret) + goto cleanup_matches; + return 0; + + cleanup_matches: + xt_ematch_foreach(ematch, e) { + if (j-- == 0) + break; + cleanup_match(ematch, net); + } + + xt_percpu_counter_free(e->counters.pcnt); + + return ret; } static int translate_compat_table(struct net *net, + const char *name, + unsigned int valid_hooks, struct xt_table_info **pinfo, void **pentry0, - const struct compat_ipt_replace *compatr) + unsigned int total_size, + unsigned int number, + unsigned int *hook_entries, + unsigned int *underflows) { unsigned int i, j; struct xt_table_info *newinfo, *info; void *pos, *entry0, *entry1; struct compat_ipt_entry *iter0; - struct ipt_replace repl; + struct ipt_entry *iter1; unsigned int size; int ret; info = *pinfo; entry0 = *pentry0; - size = compatr->size; - info->number = compatr->num_entries; + size = total_size; + info->number = number; + + /* Init all hooks to impossible value. */ + for (i = 0; i < NF_INET_NUMHOOKS; i++) { + info->hook_entry[i] = 0xFFFFFFFF; + info->underflow[i] = 0xFFFFFFFF; + } duprintf("translate_compat_table: size %u\n", info->size); j = 0; xt_compat_lock(AF_INET); - xt_compat_init_offsets(AF_INET, compatr->num_entries); + xt_compat_init_offsets(AF_INET, number); /* Walk through entries, checking offsets. */ - xt_entry_foreach(iter0, entry0, compatr->size) { + xt_entry_foreach(iter0, entry0, total_size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, - entry0 + compatr->size); + entry0 + total_size, + hook_entries, + underflows, + name); if (ret != 0) goto out_unlock; ++j; } ret = -EINVAL; - if (j != compatr->num_entries) { + if (j != number) { duprintf("translate_compat_table: %u not %u entries\n", - j, compatr->num_entries); + j, number); goto out_unlock; } + /* Check hooks all assigned */ + for (i = 0; i < NF_INET_NUMHOOKS; i++) { + /* Only hooks which are valid */ + if (!(valid_hooks & (1 << i))) + continue; + if (info->hook_entry[i] == 0xFFFFFFFF) { + duprintf("Invalid hook entry %u %u\n", + i, hook_entries[i]); + goto out_unlock; + } + if (info->underflow[i] == 0xFFFFFFFF) { + duprintf("Invalid underflow %u %u\n", + i, underflows[i]); + goto out_unlock; + } + } + ret = -ENOMEM; newinfo = xt_alloc_table_info(size); if (!newinfo) goto out_unlock; - newinfo->number = compatr->num_entries; + newinfo->number = number; for (i = 0; i < NF_INET_NUMHOOKS; i++) { - newinfo->hook_entry[i] = compatr->hook_entry[i]; - newinfo->underflow[i] = compatr->underflow[i]; + newinfo->hook_entry[i] = info->hook_entry[i]; + newinfo->underflow[i] = info->underflow[i]; } entry1 = newinfo->entries; pos = entry1; - size = compatr->size; - xt_entry_foreach(iter0, entry0, compatr->size) - compat_copy_entry_from_user(iter0, &pos, &size, - newinfo, entry1); - - /* all module references in entry0 are now gone. - * entry1/newinfo contains a 64bit ruleset that looks exactly as - * generated by 64bit userspace. - * - * Call standard translate_table() to validate all hook_entrys, - * underflows, check for loops, etc. - */ + size = total_size; + xt_entry_foreach(iter0, entry0, total_size) { + ret = compat_copy_entry_from_user(iter0, &pos, &size, + name, newinfo, entry1); + if (ret != 0) + break; + } xt_compat_flush_offsets(AF_INET); xt_compat_unlock(AF_INET); + if (ret) + goto free_newinfo; - memcpy(&repl, compatr, sizeof(*compatr)); + ret = -ELOOP; + if (!mark_source_chains(newinfo, valid_hooks, entry1)) + goto free_newinfo; - for (i = 0; i < NF_INET_NUMHOOKS; i++) { - repl.hook_entry[i] = newinfo->hook_entry[i]; - repl.underflow[i] = newinfo->underflow[i]; + i = 0; + xt_entry_foreach(iter1, entry1, newinfo->size) { + ret = compat_check_entry(iter1, net, name); + if (ret != 0) + break; + ++i; + if (strcmp(ipt_get_target(iter1)->u.user.name, + XT_ERROR_TARGET) == 0) + ++newinfo->stacksize; + } + if (ret) { + /* + * The first i matches need cleanup_entry (calls ->destroy) + * because they had called ->check already. The other j-i + * entries need only release. + */ + int skip = i; + j -= i; + xt_entry_foreach(iter0, entry0, newinfo->size) { + if (skip-- > 0) + continue; + if (j-- == 0) + break; + compat_release_entry(iter0); + } + xt_entry_foreach(iter1, entry1, newinfo->size) { + if (i-- == 0) + break; + cleanup_entry(iter1, net); + } + xt_free_table_info(newinfo); + return ret; } - - repl.num_counters = 0; - repl.counters = NULL; - repl.size = newinfo->size; - ret = translate_table(net, newinfo, entry1, &repl); - if (ret) - goto free_newinfo; *pinfo = newinfo; *pentry0 = entry1; @@ -1655,16 +1791,17 @@ translate_compat_table(struct net *net, free_newinfo: xt_free_table_info(newinfo); - return ret; -out_unlock: - xt_compat_flush_offsets(AF_INET); - xt_compat_unlock(AF_INET); - xt_entry_foreach(iter0, entry0, compatr->size) { +out: + xt_entry_foreach(iter0, entry0, total_size) { if (j-- == 0) break; compat_release_entry(iter0); } return ret; +out_unlock: + xt_compat_flush_offsets(AF_INET); + xt_compat_unlock(AF_INET); + goto out; } static int @@ -1700,7 +1837,10 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) goto free_newinfo; } - ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp); + ret = translate_compat_table(net, tmp.name, tmp.valid_hooks, + &newinfo, &loc_cpu_entry, tmp.size, + tmp.num_entries, tmp.hook_entry, + tmp.underflow); if (ret != 0) goto free_newinfo; @@ -2075,7 +2215,6 @@ static struct xt_match ipt_builtin_mt[] __read_mostly = { .checkentry = icmp_checkentry, .proto = IPPROTO_ICMP, .family = NFPROTO_IPV4, - .me = THIS_MODULE, }, }; diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 16599bae11dd..4a9e6db9df8d 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -365,7 +365,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) struct ipt_clusterip_tgt_info *cipinfo = par->targinfo; const struct ipt_entry *e = par->entryinfo; struct clusterip_config *config; - int ret, i; + int ret; if (par->nft_compat) { pr_err("cannot use CLUSTERIP target from nftables compat\n"); @@ -384,18 +384,8 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) pr_info("Please specify destination IP\n"); return -EINVAL; } - if (cipinfo->num_local_nodes > ARRAY_SIZE(cipinfo->local_nodes)) { - pr_info("bad num_local_nodes %u\n", cipinfo->num_local_nodes); - return -EINVAL; - } - for (i = 0; i < cipinfo->num_local_nodes; i++) { - if (cipinfo->local_nodes[i] - 1 >= - sizeof(config->local_nodes) * 8) { - pr_info("bad local_nodes[%d] %u\n", - i, cipinfo->local_nodes[i]); - return -EINVAL; - } - } + + /* FIXME: further sanity checks */ config = clusterip_config_find_get(par->net, e->ip.dst.s_addr, 1); if (!config) { diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 3fe8c951f427..461ca926fd39 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -158,10 +158,6 @@ static unsigned int ipv4_conntrack_local(void *priv, if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; - - if (ip_is_fragment(ip_hdr(skb))) /* IP_NODEFRAG setsockopt set */ - return NF_ACCEPT; - return nf_conntrack_in(state->net, PF_INET, state->hook, skb); } @@ -259,19 +255,15 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) struct nf_conntrack_tuple tuple; memset(&tuple, 0, sizeof(tuple)); - - lock_sock(sk); tuple.src.u3.ip = inet->inet_rcv_saddr; tuple.src.u.tcp.port = inet->inet_sport; tuple.dst.u3.ip = inet->inet_daddr; tuple.dst.u.tcp.port = inet->inet_dport; tuple.src.l3num = PF_INET; tuple.dst.protonum = sk->sk_protocol; - release_sock(sk); /* We only do TCP and SCTP at the moment: is there a better way? */ - if (tuple.dst.protonum != IPPROTO_TCP && - tuple.dst.protonum != IPPROTO_SCTP) { + if (sk->sk_protocol != IPPROTO_TCP && sk->sk_protocol != IPPROTO_SCTP) { pr_debug("SO_ORIGINAL_DST: Not a TCP/SCTP socket\n"); return -ENOPROTOOPT; } diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index ac8342dcb55e..574f7ebba0b6 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c @@ -252,16 +252,16 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, if (set_h245_addr(skb, protoff, data, dataoff, taddr, &ct->tuplehash[!dir].tuple.dst.u3, htons((port & htons(1)) ? nated_port + 1 : - nated_port))) { + nated_port)) == 0) { + /* Save ports */ + info->rtp_port[i][dir] = rtp_port; + info->rtp_port[i][!dir] = htons(nated_port); + } else { nf_ct_unexpect_related(rtp_exp); nf_ct_unexpect_related(rtcp_exp); return -1; } - /* Save ports */ - info->rtp_port[i][dir] = rtp_port; - info->rtp_port[i][!dir] = htons(nated_port); - /* Success */ pr_debug("nf_nat_h323: expect RTP %pI4:%hu->%pI4:%hu\n", &rtp_exp->tuple.src.u3.ip, @@ -370,15 +370,15 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, /* Modify signal */ if (set_h225_addr(skb, protoff, data, dataoff, taddr, &ct->tuplehash[!dir].tuple.dst.u3, - htons(nated_port))) { + htons(nated_port)) == 0) { + /* Save ports */ + info->sig_port[dir] = port; + info->sig_port[!dir] = htons(nated_port); + } else { nf_ct_unexpect_related(exp); return -1; } - /* Save ports */ - info->sig_port[dir] = port; - info->sig_port[!dir] = htons(nated_port); - pr_debug("nf_nat_q931: expect H.245 %pI4:%hu->%pI4:%hu\n", &exp->tuple.src.u3.ip, ntohs(exp->tuple.src.u.tcp.port), @@ -462,27 +462,24 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, /* Modify signal */ if (set_h225_addr(skb, protoff, data, 0, &taddr[idx], &ct->tuplehash[!dir].tuple.dst.u3, - htons(nated_port))) { + htons(nated_port)) == 0) { + /* Save ports */ + info->sig_port[dir] = port; + info->sig_port[!dir] = htons(nated_port); + + /* Fix for Gnomemeeting */ + if (idx > 0 && + get_h225_addr(ct, *data, &taddr[0], &addr, &port) && + (ntohl(addr.ip) & 0xff000000) == 0x7f000000) { + set_h225_addr(skb, protoff, data, 0, &taddr[0], + &ct->tuplehash[!dir].tuple.dst.u3, + info->sig_port[!dir]); + } + } else { nf_ct_unexpect_related(exp); return -1; } - /* Save ports */ - info->sig_port[dir] = port; - info->sig_port[!dir] = htons(nated_port); - - /* Fix for Gnomemeeting */ - if (idx > 0 && - get_h225_addr(ct, *data, &taddr[0], &addr, &port) && - (ntohl(addr.ip) & 0xff000000) == 0x7f000000) { - if (set_h225_addr(skb, protoff, data, 0, &taddr[0], - &ct->tuplehash[!dir].tuple.dst.u3, - info->sig_port[!dir])) { - nf_ct_unexpect_related(exp); - return -1; - } - } - /* Success */ pr_debug("nf_nat_ras: expect Q.931 %pI4:%hu->%pI4:%hu\n", &exp->tuple.src.u3.ip, @@ -553,9 +550,9 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, } /* Modify signal */ - if (set_h225_addr(skb, protoff, data, dataoff, taddr, - &ct->tuplehash[!dir].tuple.dst.u3, - htons(nated_port))) { + if (!set_h225_addr(skb, protoff, data, dataoff, taddr, + &ct->tuplehash[!dir].tuple.dst.u3, + htons(nated_port)) == 0) { nf_ct_unexpect_related(exp); return -1; } diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c index 98a56077f604..5075b7ecd26d 100644 --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c @@ -268,6 +268,11 @@ nf_nat_ipv4_fn(void *priv, struct sk_buff *skb, /* maniptype == SRC for postrouting. */ enum nf_nat_manip_type maniptype = HOOK2MANIP(state->hook); + /* We never see fragments: conntrack defrags on pre-routing + * and local-out, and nf_nat_out protects post-routing. + */ + NF_CT_ASSERT(!ip_is_fragment(ip_hdr(skb))); + ct = nf_ct_get(skb, &ctinfo); /* Can't track? It's not due to stress, or conntrack would * have dropped it. Hence it's the user's responsibilty to diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 182eb878633d..ddb894ac1458 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -1260,6 +1260,16 @@ static const struct nf_conntrack_expect_policy snmp_exp_policy = { .timeout = 180, }; +static struct nf_conntrack_helper snmp_helper __read_mostly = { + .me = THIS_MODULE, + .help = help, + .expect_policy = &snmp_exp_policy, + .name = "snmp", + .tuple.src.l3num = AF_INET, + .tuple.src.u.udp.port = cpu_to_be16(SNMP_PORT), + .tuple.dst.protonum = IPPROTO_UDP, +}; + static struct nf_conntrack_helper snmp_trap_helper __read_mostly = { .me = THIS_MODULE, .help = help, @@ -1278,16 +1288,22 @@ static struct nf_conntrack_helper snmp_trap_helper __read_mostly = { static int __init nf_nat_snmp_basic_init(void) { + int ret = 0; + BUG_ON(nf_nat_snmp_hook != NULL); RCU_INIT_POINTER(nf_nat_snmp_hook, help); - return nf_conntrack_helper_register(&snmp_trap_helper); + ret = nf_conntrack_helper_register(&snmp_trap_helper); + if (ret < 0) { + nf_conntrack_helper_unregister(&snmp_helper); + return ret; + } + return ret; } static void __exit nf_nat_snmp_basic_fini(void) { RCU_INIT_POINTER(nf_nat_snmp_hook, NULL); - synchronize_rcu(); nf_conntrack_helper_unregister(&snmp_trap_helper); } diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c index d4acf38b60fd..c747b2d9eb77 100644 --- a/net/ipv4/netfilter/nf_reject_ipv4.c +++ b/net/ipv4/netfilter/nf_reject_ipv4.c @@ -124,8 +124,6 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook) /* ip_route_me_harder expects skb->dst to be set */ skb_dst_set_noref(nskb, skb_dst(oldskb)); - nskb->mark = IP4_REPLY_MARK(net, oldskb->mark); - skb_reserve(nskb, LL_MAX_HEADER); niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP, ip4_dst_hoplimit(skb_dst(nskb))); diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index c0b633ee6c1e..173cb60d8c6d 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -646,8 +646,6 @@ static int ping_v4_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, { struct sk_buff *skb = skb_peek(&sk->sk_write_queue); - if (!skb) - return 0; pfh->wcheck = csum_partial((char *)&pfh->icmph, sizeof(struct icmphdr), pfh->wcheck); pfh->icmph.checksum = csum_fold(pfh->wcheck); @@ -663,10 +661,6 @@ int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, if (len > 0xFFFF || len < icmph_len) return -EMSGSIZE; - /* Must have at least a full ICMP header. */ - if (len < icmph_len) - return -EINVAL; - /* * Check the flags. */ @@ -777,10 +771,8 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) ipc.addr = faddr = daddr; if (ipc.opt && ipc.opt->opt.srr) { - if (!daddr) { - err = -EINVAL; - goto out_free; - } + if (!daddr) + return -EINVAL; faddr = ipc.opt->opt.faddr; } tos = get_rttos(&ipc, inet); @@ -846,7 +838,6 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) out: ip_rt_put(rt); -out_free: if (free) kfree(ipc.opt); if (!err) { diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 801c72b47bc2..7d9e03db833c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -126,13 +126,10 @@ static int ip_rt_redirect_silence __read_mostly = ((HZ / 50) << (9 + 1)); static int ip_rt_error_cost __read_mostly = HZ; static int ip_rt_error_burst __read_mostly = 5 * HZ; static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; -static u32 ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; +static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; static int ip_rt_min_advmss __read_mostly = 256; static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT; - -static int ip_min_valid_pmtu __read_mostly = IPV4_MIN_MTU; - /* * Interface to generic destination cache. */ @@ -615,7 +612,6 @@ static inline u32 fnhe_hashfun(__be32 daddr) static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnhe) { rt->rt_pmtu = fnhe->fnhe_pmtu; - rt->rt_mtu_locked = fnhe->fnhe_mtu_locked; rt->dst.expires = fnhe->fnhe_expires; if (fnhe->fnhe_gw) { @@ -626,17 +622,14 @@ static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnh } static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, - u32 pmtu, bool lock, unsigned long expires) + u32 pmtu, unsigned long expires) { struct fnhe_hash_bucket *hash; struct fib_nh_exception *fnhe; struct rtable *rt; - u32 genid, hval; unsigned int i; int depth; - - genid = fnhe_genid(dev_net(nh->nh_dev)); - hval = fnhe_hashfun(daddr); + u32 hval = fnhe_hashfun(daddr); spin_lock_bh(&fnhe_lock); @@ -659,15 +652,12 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, } if (fnhe) { - if (fnhe->fnhe_genid != genid) - fnhe->fnhe_genid = genid; if (gw) fnhe->fnhe_gw = gw; if (pmtu) { fnhe->fnhe_pmtu = pmtu; - fnhe->fnhe_mtu_locked = lock; + fnhe->fnhe_expires = max(1UL, expires); } - fnhe->fnhe_expires = max(1UL, expires); /* Update all cached dsts too */ rt = rcu_dereference(fnhe->fnhe_rth_input); if (rt) @@ -686,11 +676,10 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, fnhe->fnhe_next = hash->chain; rcu_assign_pointer(hash->chain, fnhe); } - fnhe->fnhe_genid = genid; + fnhe->fnhe_genid = fnhe_genid(dev_net(nh->nh_dev)); fnhe->fnhe_daddr = daddr; fnhe->fnhe_gw = gw; fnhe->fnhe_pmtu = pmtu; - fnhe->fnhe_mtu_locked = lock; fnhe->fnhe_expires = expires; /* Exception created; mark the cached routes for the nexthop @@ -761,9 +750,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow goto reject_redirect; } - n = __ipv4_neigh_lookup(rt->dst.dev, new_gw); - if (!n) - n = neigh_create(&arp_tbl, &new_gw, rt->dst.dev); + n = ipv4_neigh_lookup(&rt->dst, NULL, &new_gw); if (!IS_ERR(n)) { if (!(n->nud_state & NUD_VALID)) { neigh_event_send(n, NULL); @@ -772,8 +759,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow struct fib_nh *nh = &FIB_RES_NH(res); update_or_create_fnhe(nh, fl4->daddr, new_gw, - 0, false, - jiffies + ip_rt_gc_timeout); + 0, jiffies + ip_rt_gc_timeout); } if (kill_route) rt->dst.obsolete = DST_OBSOLETE_KILL; @@ -985,18 +971,15 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) { struct dst_entry *dst = &rt->dst; struct fib_result res; - bool lock = false; - if (ip_mtu_locked(dst)) + if (dst_metric_locked(dst, RTAX_MTU)) return; if (ipv4_mtu(dst) < mtu) return; - if (mtu < ip_rt_min_pmtu) { - lock = true; + if (mtu < ip_rt_min_pmtu) mtu = ip_rt_min_pmtu; - } if (rt->rt_pmtu == mtu && time_before(jiffies, dst->expires - ip_rt_mtu_expires / 2)) @@ -1006,7 +989,7 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) if (fib_lookup(dev_net(dst->dev), fl4, &res, 0) == 0) { struct fib_nh *nh = &FIB_RES_NH(res); - update_or_create_fnhe(nh, fl4->daddr, 0, mtu, lock, + update_or_create_fnhe(nh, fl4->daddr, 0, mtu, jiffies + ip_rt_mtu_expires); } rcu_read_unlock(); @@ -1261,9 +1244,9 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) if (mtu) return mtu; - mtu = READ_ONCE(dst->dev->mtu); + mtu = dst->dev->mtu; - if (unlikely(ip_mtu_locked(dst))) { + if (unlikely(dst_metric_locked(dst, RTAX_MTU))) { if (rt->rt_uses_gateway && mtu > 576) mtu = 576; } @@ -1376,12 +1359,8 @@ static void rt_add_uncached_list(struct rtable *rt) static void ipv4_dst_destroy(struct dst_entry *dst) { - struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst); struct rtable *rt = (struct rtable *) dst; - if (p != &dst_default_metrics && atomic_dec_and_test(&p->refcnt)) - kfree(p); - if (!list_empty(&rt->rt_uncached)) { struct uncached_list *ul = rt->rt_uncached_list; @@ -1433,11 +1412,7 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, rt->rt_gateway = nh->nh_gw; rt->rt_uses_gateway = 1; } - dst_init_metrics(&rt->dst, fi->fib_metrics->metrics, true); - if (fi->fib_metrics != &dst_default_metrics) { - rt->dst._metrics |= DST_METRICS_REFCOUNTED; - atomic_inc(&fi->fib_metrics->refcnt); - } + dst_init_metrics(&rt->dst, fi->fib_metrics, true); #ifdef CONFIG_IP_ROUTE_CLASSID rt->dst.tclassid = nh->nh_tclassid; #endif @@ -1486,7 +1461,6 @@ static struct rtable *rt_dst_alloc(struct net_device *dev, rt->rt_is_input = 0; rt->rt_iif = 0; rt->rt_pmtu = 0; - rt->rt_mtu_locked = 0; rt->rt_gateway = 0; rt->rt_uses_gateway = 0; rt->rt_table_id = 0; @@ -1987,7 +1961,6 @@ int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr, { int res; - tos &= IPTOS_RT_MASK; rcu_read_lock(); /* Multicast recognition logic is moved from route cache to here. @@ -2407,7 +2380,6 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or rt->rt_is_input = ort->rt_is_input; rt->rt_iif = ort->rt_iif; rt->rt_pmtu = ort->rt_pmtu; - rt->rt_mtu_locked = ort->rt_mtu_locked; rt->rt_genid = rt_genid_ipv4(net); rt->rt_flags = ort->rt_flags; @@ -2461,7 +2433,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id, r->rtm_dst_len = 32; r->rtm_src_len = 0; r->rtm_tos = fl4->flowi4_tos; - r->rtm_table = table_id < 256 ? table_id : RT_TABLE_COMPAT; + r->rtm_table = table_id; if (nla_put_u32(skb, RTA_TABLE, table_id)) goto nla_put_failure; r->rtm_type = rt->rt_type; @@ -2510,8 +2482,6 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id, memcpy(metrics, dst_metrics_ptr(&rt->dst), sizeof(metrics)); if (rt->rt_pmtu && expires) metrics[RTAX_MTU - 1] = rt->rt_pmtu; - if (rt->rt_mtu_locked && expires) - metrics[RTAX_LOCK - 1] |= BIT(RTAX_MTU); if (rtnetlink_put_metrics(skb, metrics) < 0) goto nla_put_failure; @@ -2532,8 +2502,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id, IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { int err = ipmr_get_route(net, skb, fl4->saddr, fl4->daddr, - r, nowait, portid); - + r, nowait); if (err <= 0) { if (!nowait) { if (err == 0) @@ -2597,7 +2566,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh) skb_reset_network_header(skb); /* Bugfix: need to give ip_route_input enough of an IP header to not gag. */ - ip_hdr(skb)->protocol = IPPROTO_UDP; + ip_hdr(skb)->protocol = IPPROTO_ICMP; skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr)); src = tb[RTA_SRC] ? nla_get_in_addr(tb[RTA_SRC]) : 0; @@ -2796,8 +2765,7 @@ static struct ctl_table ipv4_route_table[] = { .data = &ip_rt_min_pmtu, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, - .extra1 = &ip_min_valid_pmtu, + .proc_handler = proc_dointvec, }, { .procname = "min_adv_mss", diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index ed0f1a0a4525..dab594823452 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -376,7 +376,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) treq = tcp_rsk(req); treq->rcv_isn = ntohl(th->seq) - 1; treq->snt_isn = cookie; - treq->txhash = net_tx_rndhash(); req->mss = mss; ireq->ir_num = ntohs(th->dest); ireq->ir_rmt_port = th->source; @@ -405,7 +404,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) /* We throwed the options of the initial SYN away, so we hope * the ACK carries the same options again (see RFC1122 4.2.3.8) */ - RCU_INIT_POINTER(ireq->ireq_opt, tcp_v4_save_options(skb)); + ireq->opt = tcp_v4_save_options(skb); if (security_inet_conn_request(sk, skb, req)) { reqsk_free(req); diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index b2daf343d085..a16b9498ea4f 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -97,11 +97,11 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low container_of(table->data, struct net, ipv4.ping_group_range.range); unsigned int seq; do { - seq = read_seqbegin(&net->ipv4.ping_group_range.lock); + seq = read_seqbegin(&net->ipv4.ip_local_ports.lock); *low = data[0]; *high = data[1]; - } while (read_seqretry(&net->ipv4.ping_group_range.lock, seq)); + } while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq)); } /* Update system visible IP port range */ @@ -110,10 +110,10 @@ static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t hig kgid_t *data = table->data; struct net *net = container_of(table->data, struct net, ipv4.ping_group_range.range); - write_seqlock(&net->ipv4.ping_group_range.lock); + write_seqlock(&net->ipv4.ip_local_ports.lock); data[0] = low; data[1] = high; - write_sequnlock(&net->ipv4.ping_group_range.lock); + write_sequnlock(&net->ipv4.ip_local_ports.lock); } /* Validate changes from /proc interface. */ @@ -141,9 +141,8 @@ static int ipv4_ping_group_range(struct ctl_table *table, int write, if (write && ret == 0) { low = make_kgid(user_ns, urange[0]); high = make_kgid(user_ns, urange[1]); - if (!gid_valid(low) || !gid_valid(high)) - return -EINVAL; - if (urange[1] < urange[0] || gid_lt(high, low)) { + if (!gid_valid(low) || !gid_valid(high) || + (urange[1] < urange[0]) || gid_lt(high, low)) { low = make_kgid(&init_user_ns, 1); high = make_kgid(&init_user_ns, 0); } @@ -229,9 +228,8 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write, { struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) }; struct tcp_fastopen_context *ctxt; + int ret; u32 user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */ - __le32 key[4]; - int ret, i; tbl.data = kmalloc(tbl.maxlen, GFP_KERNEL); if (!tbl.data) @@ -240,14 +238,11 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write, rcu_read_lock(); ctxt = rcu_dereference(tcp_fastopen_ctx); if (ctxt) - memcpy(key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH); + memcpy(user_key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH); else - memset(key, 0, sizeof(key)); + memset(user_key, 0, sizeof(user_key)); rcu_read_unlock(); - for (i = 0; i < ARRAY_SIZE(key); i++) - user_key[i] = le32_to_cpu(key[i]); - snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x", user_key[0], user_key[1], user_key[2], user_key[3]); ret = proc_dostring(&tbl, write, buffer, lenp, ppos); @@ -263,16 +258,12 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write, * first invocation of tcp_fastopen_cookie_gen */ tcp_fastopen_init_key_once(false); - - for (i = 0; i < ARRAY_SIZE(user_key); i++) - key[i] = cpu_to_le32(user_key[i]); - - tcp_fastopen_reset_cipher(key, TCP_FASTOPEN_KEY_LENGTH); + tcp_fastopen_reset_cipher(user_key, TCP_FASTOPEN_KEY_LENGTH); } bad_key: pr_debug("proc FO key set 0x%x-%x-%x-%x <- 0x%s: %u\n", - user_key[0], user_key[1], user_key[2], user_key[3], + user_key[0], user_key[1], user_key[2], user_key[3], (char *)tbl.data, ret); kfree(tbl.data); return ret; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 916ebfc4a3e3..ec4a3aa9060c 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1157,12 +1157,9 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *copied, size_t size) { struct tcp_sock *tp = tcp_sk(sk); - struct sockaddr *uaddr = msg->msg_name; int err, flags; - if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) || - (uaddr && msg->msg_namelen >= sizeof(uaddr->sa_family) && - uaddr->sa_family == AF_UNSPEC)) + if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE)) return -EOPNOTSUPP; if (tp->fastopen_req) return -EALREADY; /* Another Fast Open is in progress */ @@ -1175,7 +1172,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, tp->fastopen_req->size = size; flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0; - err = __inet_stream_connect(sk->sk_socket, uaddr, + err = __inet_stream_connect(sk->sk_socket, msg->msg_name, msg->msg_namelen, flags); *copied = tp->fastopen_req->copied; tcp_free_fastopen_req(tp); @@ -1194,7 +1191,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) lock_sock(sk); flags = msg->msg_flags; - if ((flags & MSG_FASTOPEN) && !tp->repair) { + if (flags & MSG_FASTOPEN) { err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size); if (err == -EINPROGRESS && copied_syn > 0) goto out; @@ -1346,7 +1343,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) if (!skb_can_coalesce(skb, i, pfrag->page, pfrag->offset)) { - if (i >= sysctl_max_skb_frags || !sg) { + if (i == sysctl_max_skb_frags || !sg) { tcp_mark_push(tp, skb); goto new_segment; } @@ -1803,7 +1800,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, * shouldn't happen. */ if (WARN(before(*seq, TCP_SKB_CB(skb)->seq), - "TCP recvmsg seq # bug: copied %X, seq %X, rcvnxt %X, fl %X\n", + "recvmsg bug: copied %X seq %X rcvnxt %X fl %X\n", *seq, TCP_SKB_CB(skb)->seq, tp->rcv_nxt, flags)) break; @@ -1816,7 +1813,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) goto found_fin_ok; WARN(!(flags & MSG_PEEK), - "TCP recvmsg seq # bug 2: copied %X, seq %X, rcvnxt %X, fl %X\n", + "recvmsg bug 2: copied %X seq %X rcvnxt %X fl %X\n", *seq, TCP_SKB_CB(skb)->seq, tp->rcv_nxt, flags); } @@ -2359,9 +2356,6 @@ void tcp_close(struct sock *sk, long timeout) #endif NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY); - } else if (!check_net(sock_net(sk))) { - /* Not possible to send reset; just close */ - tcp_set_state(sk, TCP_CLOSE); } } @@ -2468,18 +2462,9 @@ int tcp_disconnect(struct sock *sk, int flags) tcp_init_send_head(sk); memset(&tp->rx_opt, 0, sizeof(tp->rx_opt)); __sk_dst_reset(sk); - dst_release(sk->sk_rx_dst); - sk->sk_rx_dst = NULL; - tcp_saved_syn_free(tp); WARN_ON(inet->inet_num && !icsk->icsk_bind_hash); - if (sk->sk_frag.page) { - put_page(sk->sk_frag.page); - sk->sk_frag.page = NULL; - sk->sk_frag.offset = 0; - } - sk->sk_error_report(sk); return err; } @@ -2648,7 +2633,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, case TCP_REPAIR_QUEUE: if (!tp->repair) err = -EPERM; - else if ((unsigned int)val < TCP_QUEUES_NR) + else if (val < TCP_QUEUES_NR) tp->repair_queue = val; else err = -EINVAL; @@ -2799,10 +2784,8 @@ static int do_tcp_setsockopt(struct sock *sk, int level, #ifdef CONFIG_TCP_MD5SIG case TCP_MD5SIG: - if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) - err = tp->af_specific->md5_parse(sk, optval, optlen); - else - err = -EINVAL; + /* Read the IP->Key mappings from userspace */ + err = tp->af_specific->md5_parse(sk, optval, optlen); break; #endif case TCP_USER_TIMEOUT: diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index aafe68134763..882caa4e72bc 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -183,7 +183,6 @@ void tcp_init_congestion_control(struct sock *sk) { const struct inet_connection_sock *icsk = inet_csk(sk); - tcp_sk(sk)->prior_ssthresh = 0; if (icsk->icsk_ca_ops->init) icsk->icsk_ca_ops->init(sk); if (tcp_ca_needs_ecn(sk)) diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c index 62f90f6b7a9d..7e538f71f5fb 100644 --- a/net/ipv4/tcp_dctcp.c +++ b/net/ipv4/tcp_dctcp.c @@ -55,7 +55,7 @@ struct dctcp { u32 dctcp_alpha; u32 next_seq; u32 ce_state; - u32 loss_cwnd; + u32 delayed_ack_reserved; }; static unsigned int dctcp_shift_g __read_mostly = 4; /* g = 1/2^4 */ @@ -95,7 +95,7 @@ static void dctcp_init(struct sock *sk) ca->dctcp_alpha = min(dctcp_alpha_on_init, DCTCP_MAX_ALPHA); - ca->loss_cwnd = 0; + ca->delayed_ack_reserved = 0; ca->ce_state = 0; dctcp_reset(tp, ca); @@ -111,10 +111,9 @@ static void dctcp_init(struct sock *sk) static u32 dctcp_ssthresh(struct sock *sk) { - struct dctcp *ca = inet_csk_ca(sk); + const struct dctcp *ca = inet_csk_ca(sk); struct tcp_sock *tp = tcp_sk(sk); - ca->loss_cwnd = tp->snd_cwnd; return max(tp->snd_cwnd - ((tp->snd_cwnd * ca->dctcp_alpha) >> 11U), 2U); } @@ -129,14 +128,23 @@ static void dctcp_ce_state_0_to_1(struct sock *sk) struct dctcp *ca = inet_csk_ca(sk); struct tcp_sock *tp = tcp_sk(sk); - if (!ca->ce_state) { - /* State has changed from CE=0 to CE=1, force an immediate - * ACK to reflect the new CE state. If an ACK was delayed, - * send that first to reflect the prior CE state. - */ - if (inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER) - __tcp_send_ack(sk, ca->prior_rcv_nxt); - tcp_enter_quickack_mode(sk, 1); + /* State has changed from CE=0 to CE=1 and delayed + * ACK has not sent yet. + */ + if (!ca->ce_state && ca->delayed_ack_reserved) { + u32 tmp_rcv_nxt; + + /* Save current rcv_nxt. */ + tmp_rcv_nxt = tp->rcv_nxt; + + /* Generate previous ack with CE=0. */ + tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR; + tp->rcv_nxt = ca->prior_rcv_nxt; + + tcp_send_ack(sk); + + /* Recover current rcv_nxt. */ + tp->rcv_nxt = tmp_rcv_nxt; } ca->prior_rcv_nxt = tp->rcv_nxt; @@ -150,14 +158,23 @@ static void dctcp_ce_state_1_to_0(struct sock *sk) struct dctcp *ca = inet_csk_ca(sk); struct tcp_sock *tp = tcp_sk(sk); - if (ca->ce_state) { - /* State has changed from CE=1 to CE=0, force an immediate - * ACK to reflect the new CE state. If an ACK was delayed, - * send that first to reflect the prior CE state. - */ - if (inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER) - __tcp_send_ack(sk, ca->prior_rcv_nxt); - tcp_enter_quickack_mode(sk, 1); + /* State has changed from CE=1 to CE=0 and delayed + * ACK has not sent yet. + */ + if (ca->ce_state && ca->delayed_ack_reserved) { + u32 tmp_rcv_nxt; + + /* Save current rcv_nxt. */ + tmp_rcv_nxt = tp->rcv_nxt; + + /* Generate previous ack with CE=1. */ + tp->ecn_flags |= TCP_ECN_DEMAND_CWR; + tp->rcv_nxt = ca->prior_rcv_nxt; + + tcp_send_ack(sk); + + /* Recover current rcv_nxt. */ + tp->rcv_nxt = tmp_rcv_nxt; } ca->prior_rcv_nxt = tp->rcv_nxt; @@ -228,6 +245,25 @@ static void dctcp_state(struct sock *sk, u8 new_state) } } +static void dctcp_update_ack_reserved(struct sock *sk, enum tcp_ca_event ev) +{ + struct dctcp *ca = inet_csk_ca(sk); + + switch (ev) { + case CA_EVENT_DELAYED_ACK: + if (!ca->delayed_ack_reserved) + ca->delayed_ack_reserved = 1; + break; + case CA_EVENT_NON_DELAYED_ACK: + if (ca->delayed_ack_reserved) + ca->delayed_ack_reserved = 0; + break; + default: + /* Don't care for the rest. */ + break; + } +} + static void dctcp_cwnd_event(struct sock *sk, enum tcp_ca_event ev) { switch (ev) { @@ -237,6 +273,10 @@ static void dctcp_cwnd_event(struct sock *sk, enum tcp_ca_event ev) case CA_EVENT_ECN_NO_CE: dctcp_ce_state_1_to_0(sk); break; + case CA_EVENT_DELAYED_ACK: + case CA_EVENT_NON_DELAYED_ACK: + dctcp_update_ack_reserved(sk, ev); + break; default: /* Don't care for the rest. */ break; @@ -268,20 +308,12 @@ static size_t dctcp_get_info(struct sock *sk, u32 ext, int *attr, return 0; } -static u32 dctcp_cwnd_undo(struct sock *sk) -{ - const struct dctcp *ca = inet_csk_ca(sk); - - return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd); -} - static struct tcp_congestion_ops dctcp __read_mostly = { .init = dctcp_init, .in_ack_event = dctcp_update_alpha, .cwnd_event = dctcp_cwnd_event, .ssthresh = dctcp_ssthresh, .cong_avoid = tcp_reno_cong_avoid, - .undo_cwnd = dctcp_cwnd_undo, .set_state = dctcp_state, .get_info = dctcp_get_info, .flags = TCP_CONG_NEEDS_ECN, diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index 63c47f747050..aefa552427c4 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c @@ -115,7 +115,7 @@ static bool tcp_fastopen_cookie_gen(struct request_sock *req, struct tcp_fastopen_cookie tmp; if (__tcp_fastopen_cookie_gen(&ip6h->saddr, &tmp)) { - struct in6_addr *buf = &tmp.addr; + struct in6_addr *buf = (struct in6_addr *) tmp.val; int i; for (i = 0; i < 4; i++) @@ -167,7 +167,6 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk, * scaled. So correct it appropriately. */ tp->snd_wnd = ntohs(tcp_hdr(skb)->window); - tp->max_window = tp->snd_wnd; /* Activate the retrans timer so that SYNACK can be retransmitted. * The request socket is not added to the ehash diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index 5ed6a89894fd..2ab9bbb6faff 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c @@ -6,7 +6,7 @@ * The algorithm is described in: * "TCP-Illinois: A Loss and Delay-Based Congestion Control Algorithm * for High-Speed Networks" - * http://tamerbasar.csl.illinois.edu/LiuBasarSrikantPerfEvalArtJun2008.pdf + * http://www.ifp.illinois.edu/~srikant/Papers/liubassri06perf.pdf * * Implemented from description in paper and ns-2 simulation. * Copyright (C) 2007 Stephen Hemminger diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 8488547328aa..db3199ac3039 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -131,7 +131,6 @@ unsigned long long sysctl_tcp_cltcp_ifdevs __read_mostly; #define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */ #define FLAG_SACK_RENEGING 0x2000 /* snd_una advanced to a sacked seq */ #define FLAG_UPDATE_TS_RECENT 0x4000 /* tcp_replace_ts_recent() */ -#define FLAG_NO_CHALLENGE_ACK 0x8000 /* do not call tcp_send_challenge_ack() */ #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) @@ -286,30 +285,27 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) } } -static void tcp_incr_quickack(struct sock *sk, unsigned int max_quickacks) +static void tcp_incr_quickack(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); unsigned int quickacks = tcp_sk(sk)->rcv_wnd / (2 * icsk->icsk_ack.rcv_mss); if (quickacks == 0) quickacks = 2; - quickacks = min(quickacks, max_quickacks); if (quickacks > icsk->icsk_ack.quick) - icsk->icsk_ack.quick = quickacks; + icsk->icsk_ack.quick = min(quickacks, TCP_MAX_QUICKACKS); } #ifndef CONFIG_MPTCP static #endif -void tcp_enter_quickack_mode(struct sock *sk, unsigned int max_quickacks) +void tcp_enter_quickack_mode(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); - - tcp_incr_quickack(sk, max_quickacks); + tcp_incr_quickack(sk); icsk->icsk_ack.pingpong = 0; icsk->icsk_ack.ato = TCP_ATO_MIN; } -EXPORT_SYMBOL(tcp_enter_quickack_mode); /* Send ACKs quickly, if "quick" count is not exhausted * and the session is not interactive. @@ -341,10 +337,8 @@ static void tcp_ecn_withdraw_cwr(struct tcp_sock *tp) tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR; } -static void __tcp_ecn_check_ce(struct sock *sk, const struct sk_buff *skb) +static void __tcp_ecn_check_ce(struct tcp_sock *tp, const struct sk_buff *skb) { - struct tcp_sock *tp = tcp_sk(sk); - switch (TCP_SKB_CB(skb)->ip_dsfield & INET_ECN_MASK) { case INET_ECN_NOT_ECT: /* Funny extension: if ECT is not set on a segment, @@ -352,31 +346,31 @@ static void __tcp_ecn_check_ce(struct sock *sk, const struct sk_buff *skb) * it is probably a retransmit. */ if (tp->ecn_flags & TCP_ECN_SEEN) - tcp_enter_quickack_mode(sk, 2); + tcp_enter_quickack_mode((struct sock *)tp); break; case INET_ECN_CE: - if (tcp_ca_needs_ecn(sk)) - tcp_ca_event(sk, CA_EVENT_ECN_IS_CE); + if (tcp_ca_needs_ecn((struct sock *)tp)) + tcp_ca_event((struct sock *)tp, CA_EVENT_ECN_IS_CE); if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) { /* Better not delay acks, sender can have a very low cwnd */ - tcp_enter_quickack_mode(sk, 2); + tcp_enter_quickack_mode((struct sock *)tp); tp->ecn_flags |= TCP_ECN_DEMAND_CWR; } tp->ecn_flags |= TCP_ECN_SEEN; break; default: - if (tcp_ca_needs_ecn(sk)) - tcp_ca_event(sk, CA_EVENT_ECN_NO_CE); + if (tcp_ca_needs_ecn((struct sock *)tp)) + tcp_ca_event((struct sock *)tp, CA_EVENT_ECN_NO_CE); tp->ecn_flags |= TCP_ECN_SEEN; break; } } -static void tcp_ecn_check_ce(struct sock *sk, const struct sk_buff *skb) +static void tcp_ecn_check_ce(struct tcp_sock *tp, const struct sk_buff *skb) { - if (tcp_sk(sk)->ecn_flags & TCP_ECN_OK) - __tcp_ecn_check_ce(sk, skb); + if (tp->ecn_flags & TCP_ECN_OK) + __tcp_ecn_check_ce(tp, skb); } static void tcp_ecn_rcv_synack(struct tcp_sock *tp, const struct tcphdr *th) @@ -919,8 +913,8 @@ static void cltcp_rwnd_max_adjustment(struct tcp_sock *tp) void tcp_rcv_space_adjust(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); - u32 copied; int time; + int copied; time = tcp_time_stamp - tp->rcvq_space.time; #ifdef CONFIG_MPTCP @@ -964,13 +958,12 @@ void tcp_rcv_space_adjust(struct sock *sk) if (sysctl_tcp_moderate_rcvbuf && !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) { - int rcvmem, rcvbuf; - u64 rcvwin; + int rcvwin, rcvmem, rcvbuf; /* minimal window to cope with packet losses, assuming * steady state. Add some cushion because of small variations. */ - rcvwin = ((u64)copied << 1) + 16 * tp->advmss; + rcvwin = (copied << 1) + 16 * tp->advmss; /* If rate increased by 25%, * assume slow start, rcvwin = 3 * copied @@ -994,12 +987,10 @@ void tcp_rcv_space_adjust(struct sock *sk) if (cltcp(tp)) { cltcp_rwnd_max_adjustment(tp); - do_div(rcvwin, tp->advmss); - rcvbuf = min_t(u64, rcvwin * rcvmem, cltcp_rmem_max(tp)); + rcvbuf = min(rcvwin / tp->advmss * rcvmem, cltcp_rmem_max(tp)); } else #endif - do_div(rcvwin, tp->advmss); - rcvbuf = min_t(u64, rcvwin * rcvmem, sysctl_tcp_rmem[2]); + rcvbuf = min(rcvwin / tp->advmss * rcvmem, sysctl_tcp_rmem[2]); #ifdef CONFIG_CLTCP cltcp_debug("%s final rcvbuf %d\n", __func__, rcvbuf); @@ -1008,7 +999,7 @@ void tcp_rcv_space_adjust(struct sock *sk) sk->sk_rcvbuf = rcvbuf; /* Make the window clamp follow along. */ - tp->window_clamp = tcp_win_from_space(rcvbuf); + tp->window_clamp = rcvwin; } #ifdef CONFIG_CLTCP else if (cltcp(tp) && cltcp_rmem_max(tp) < sk->sk_rcvbuf){ @@ -1053,7 +1044,7 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb) /* The _first_ data packet received, initialize * delayed ACK engine. */ - tcp_incr_quickack(sk, TCP_MAX_QUICKACKS); + tcp_incr_quickack(sk); icsk->icsk_ack.ato = TCP_ATO_MIN; } else { int m = now - icsk->icsk_ack.lrcvtime; @@ -1069,13 +1060,13 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb) /* Too long gap. Apparently sender failed to * restart window, so that we send ACKs quickly. */ - tcp_incr_quickack(sk, TCP_MAX_QUICKACKS); + tcp_incr_quickack(sk); sk_mem_reclaim(sk); } } icsk->icsk_ack.lrcvtime = now; - tcp_ecn_check_ce(sk, skb); + tcp_ecn_check_ce(tp, skb); if (skb->len >= 128) tcp_grow_window(sk, skb); @@ -1543,14 +1534,13 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb, */ if (pkt_len > mss) { unsigned int new_len = (pkt_len / mss) * mss; - if (!in_sack && new_len < pkt_len) + if (!in_sack && new_len < pkt_len) { new_len += mss; + if (new_len >= skb->len) + return 0; + } pkt_len = new_len; } - - if (pkt_len >= skb->len && !in_sack) - return 0; - err = tcp_fragment(sk, skb, pkt_len, mss, GFP_ATOMIC); if (err < 0) return err; @@ -2582,7 +2572,8 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) { struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; - int cnt, oldcnt, lost; + int cnt, oldcnt; + int err; unsigned int mss; /* Use SACK to deduce losses of new sequences sent during recovery */ const u32 loss_high = tcp_is_sack(tp) ? tp->snd_nxt : tp->high_seq; @@ -2622,10 +2613,9 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) break; mss = tcp_skb_mss(skb); - /* If needed, chop off the prefix to mark as lost. */ - lost = (packets - oldcnt) * mss; - if (lost < skb->len && - tcp_fragment(sk, skb, lost, mss, GFP_ATOMIC) < 0) + err = tcp_fragment(sk, skb, (packets - oldcnt) * mss, + mss, GFP_ATOMIC); + if (err < 0) break; cnt = packets; } @@ -2742,9 +2732,10 @@ static void DBGUNDO(struct sock *sk, const char *msg) } #if IS_ENABLED(CONFIG_IPV6) else if (sk->sk_family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); pr_debug("Undo %s %pI6/%u c%u l%u ss%u/%u p%u\n", msg, - &sk->sk_v6_daddr, ntohs(inet->inet_dport), + &np->daddr, ntohs(inet->inet_dport), tp->snd_cwnd, tcp_left_out(tp), tp->snd_ssthresh, tp->prior_ssthresh, tp->packets_out); @@ -2920,8 +2911,8 @@ static inline void tcp_end_cwnd_reduction(struct sock *sk) struct tcp_sock *tp = tcp_sk(sk); /* Reset cwnd to ssthresh in CWR or Recovery (unless it's undone) */ - if (tp->snd_ssthresh < TCP_INFINITE_SSTHRESH && - (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR || tp->undo_marker)) { + if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR || + (tp->undo_marker && tp->snd_ssthresh < TCP_INFINITE_SSTHRESH)) { tp->snd_cwnd = tp->snd_ssthresh; tp->snd_cwnd_stamp = tcp_time_stamp; } @@ -3449,7 +3440,8 @@ void tcp_rearm_rto(struct sock *sk) /* delta may not be positive if the socket is locked * when the retrans timer fires and is rescheduled. */ - rto = max(delta, 1); + if (delta > 0) + rto = delta; } inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto, TCP_RTO_MAX); @@ -3643,20 +3635,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, if (tcp_is_reno(tp)) { tcp_remove_reno_sacks(sk, pkts_acked); - - /* If any of the cumulatively ACKed segments was - * retransmitted, non-SACK case cannot confirm that - * progress was due to original transmission due to - * lack of TCPCB_SACKED_ACKED bits even if some of - * the packets may have been never retransmitted. - */ - if (flag & FLAG_RETRANS_DATA_ACKED) - flag &= ~FLAG_ORIG_SACK_ACKED; } else { int delta; /* Non-retransmitted hole got filled? That's reordering */ - if (reord < prior_fackets && reord <= tp->fackets_out) + if (reord < prior_fackets) tcp_update_reordering(sk, tp->fackets_out - reord, 0); delta = tcp_is_fack(tp) ? pkts_acked : @@ -3834,23 +3817,6 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32 return flag; } -static bool __tcp_oow_rate_limited(struct net *net, int mib_idx, - u32 *last_oow_ack_time) -{ - if (*last_oow_ack_time) { - s32 elapsed = (s32)(tcp_time_stamp - *last_oow_ack_time); - - if (0 <= elapsed && elapsed < sysctl_tcp_invalid_ratelimit) { - NET_INC_STATS_BH(net, mib_idx); - return true; /* rate-limited: don't send yet! */ - } - } - - *last_oow_ack_time = tcp_time_stamp; - - return false; /* not rate-limited: go ahead, send dupack now! */ -} - /* Return true if we're currently rate-limiting out-of-window ACKs and * thus shouldn't send a dupack right now. We rate-limit dupacks in * response to out-of-window SYNs or ACKs to mitigate ACK loops or DoS @@ -3864,9 +3830,21 @@ bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb, /* Data packets without SYNs are not likely part of an ACK loop. */ if ((TCP_SKB_CB(skb)->seq != TCP_SKB_CB(skb)->end_seq) && !tcp_hdr(skb)->syn) - return false; + goto not_rate_limited; + + if (*last_oow_ack_time) { + s32 elapsed = (s32)(tcp_time_stamp - *last_oow_ack_time); + + if (0 <= elapsed && elapsed < sysctl_tcp_invalid_ratelimit) { + NET_INC_STATS_BH(net, mib_idx); + return true; /* rate-limited: don't send yet! */ + } + } - return __tcp_oow_rate_limited(net, mib_idx, last_oow_ack_time); + *last_oow_ack_time = tcp_time_stamp; + +not_rate_limited: + return false; /* not rate-limited: go ahead, send dupack now! */ } /* RFC 5961 7 [ACK Throttling] */ @@ -3880,23 +3858,23 @@ static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb) u32 count; /* First check our per-socket dupack rate limit. */ - if (__tcp_oow_rate_limited(sock_net(sk), - LINUX_MIB_TCPACKSKIPPEDCHALLENGE, - &tp->last_oow_ack_time)) + if (tcp_oow_rate_limited(sock_net(sk), skb, + LINUX_MIB_TCPACKSKIPPEDCHALLENGE, + &tp->last_oow_ack_time)) return; - /* Then check host-wide RFC 5961 rate limit. */ + /* Then check the check host-wide RFC 5961 rate limit. */ now = jiffies / HZ; if (now != challenge_timestamp) { u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1; challenge_timestamp = now; - WRITE_ONCE(challenge_count, half + - prandom_u32_max(sysctl_tcp_challenge_ack_limit)); + challenge_count = half + + prandom_u32_max(sysctl_tcp_challenge_ack_limit); } - count = READ_ONCE(challenge_count); + count = challenge_count; if (count > 0) { - WRITE_ONCE(challenge_count, count - 1); + challenge_count = count - 1; NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); tcp_send_ack(sk); } @@ -3993,8 +3971,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) if (before(ack, prior_snd_una)) { /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */ if (before(ack, prior_snd_una - tp->max_window)) { - if (!(flag & FLAG_NO_CHALLENGE_ACK)) - tcp_send_challenge_ack(sk, skb); + tcp_send_challenge_ack(sk, skb); return -1; } goto old_ack; @@ -4347,8 +4324,11 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th) int length = (th->doff << 2) - sizeof(*th); const u8 *ptr = (const u8 *)(th + 1); - /* If not enough data remaining, we can short cut */ - while (length >= TCPOLEN_MD5SIG) { + /* If the TCP option is too short, we can short cut */ + if (length < TCPOLEN_MD5SIG) + return NULL; + + while (length > 0) { int opcode = *ptr++; int opsize; @@ -4625,7 +4605,7 @@ static void tcp_send_dupack(struct sock *sk, const struct sk_buff *skb) if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOST); - tcp_enter_quickack_mode(sk, TCP_MAX_QUICKACKS); + tcp_enter_quickack_mode(sk); if (tcp_is_sack(tp) && sysctl_tcp_dsack) { u32 end_seq = TCP_SKB_CB(skb)->end_seq; @@ -4878,7 +4858,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) struct sk_buff *skb1; u32 seq, end_seq; - tcp_ecn_check_ce(sk, skb); + tcp_ecn_check_ce(tp, skb); if (unlikely(tcp_try_rmem_schedule(sk, skb, skb->truesize))) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFODROP); @@ -5189,7 +5169,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) tcp_dsack_set(sk, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq); out_of_window: - tcp_enter_quickack_mode(sk, TCP_MAX_QUICKACKS); + tcp_enter_quickack_mode(sk); inet_csk_schedule_ack(sk); drop: __kfree_skb(skb); @@ -5200,6 +5180,8 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt + tcp_receive_window(tp))) goto out_of_window; + tcp_enter_quickack_mode(sk); + if (before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { /* Partial packet, seq < rcv_next < end_seq */ SOCK_DEBUG(sk, "partial packet: rcv_next %X seq %X - %X\n", @@ -5342,7 +5324,6 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, static void tcp_collapse_ofo_queue(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); - u32 range_truesize, sum_tiny = 0; struct sk_buff *skb = skb_peek(&tp->out_of_order_queue); struct sk_buff *head; u32 start, end; @@ -5352,7 +5333,6 @@ static void tcp_collapse_ofo_queue(struct sock *sk) start = TCP_SKB_CB(skb)->seq; end = TCP_SKB_CB(skb)->end_seq; - range_truesize = skb->truesize; head = skb; for (;;) { @@ -5367,26 +5347,15 @@ static void tcp_collapse_ofo_queue(struct sock *sk) if (!skb || after(TCP_SKB_CB(skb)->seq, end) || before(TCP_SKB_CB(skb)->end_seq, start)) { - /* Do not attempt collapsing tiny skbs */ - if (range_truesize != head->truesize || - end - start >= SKB_WITH_OVERHEAD(SK_MEM_QUANTUM)) { - tcp_collapse(sk, &tp->out_of_order_queue, - head, skb, start, end); - } else { - sum_tiny += range_truesize; - if (sum_tiny > sk->sk_rcvbuf >> 3) - return; - } - + tcp_collapse(sk, &tp->out_of_order_queue, + head, skb, start, end); head = skb; if (!skb) break; /* Start new segment */ start = TCP_SKB_CB(skb)->seq; end = TCP_SKB_CB(skb)->end_seq; - range_truesize = skb->truesize; } else { - range_truesize += skb->truesize; if (before(TCP_SKB_CB(skb)->seq, start)) start = TCP_SKB_CB(skb)->seq; if (after(TCP_SKB_CB(skb)->end_seq, end)) @@ -5444,9 +5413,6 @@ static int tcp_prune_queue(struct sock *sk) else if (tcp_under_memory_pressure(sk)) tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss); - if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) - return 0; - tcp_collapse_ofo_queue(sk); if (!skb_queue_empty(&sk->sk_receive_queue)) tcp_collapse(sk, &sk->sk_receive_queue, @@ -5560,7 +5526,7 @@ static void tcp_check_space(struct sock *sk) if (sock_flag(sk, SOCK_QUEUE_SHRUNK)) { sock_reset_flag(sk, SOCK_QUEUE_SHRUNK); /* pairs with tcp_poll() */ - smp_mb(); + smp_mb__after_atomic(); if #ifdef CONFIG_MPTCP (mptcp(tcp_sk(sk)) || @@ -6083,7 +6049,6 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb) struct inet_connection_sock *icsk = inet_csk(sk); tcp_set_state(sk, TCP_ESTABLISHED); - icsk->icsk_ack.lrcvtime = tcp_time_stamp; if (skb) { icsk->icsk_af_ops->sk_rx_dst_set(sk, skb); @@ -6116,6 +6081,10 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb) else tp->pred_flags = 0; + if (!sock_flag(sk, SOCK_DEAD)) { + sk->sk_state_change(sk); + sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT); + } } static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, @@ -6191,7 +6160,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, struct tcp_sock *tp = tcp_sk(sk); struct tcp_fastopen_cookie foc = { .len = -1 }; int saved_clamp = tp->rx_opt.mss_clamp; - bool fastopen_fail; #ifdef CONFIG_MPTCP @@ -6335,19 +6303,14 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, tcp_finish_connect(sk, skb); - fastopen_fail = (tp->syn_fastopen || tp->syn_data) && - tcp_rcv_fastopen_synack(sk, skb, &foc); + if ((tp->syn_fastopen || tp->syn_data) && + tcp_rcv_fastopen_synack(sk, skb, &foc)) + return -1; /* With MPTCP we cannot send data on the third ack due to the * lack of option-space to combine with an MP_CAPABLE. */ - - if (!sock_flag(sk, SOCK_DEAD)) { - sk->sk_state_change(sk); - sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT); - } - if (fastopen_fail) - return -1; + if ( #ifdef CONFIG_MPTCP !mptcp(tp) && ( @@ -6367,7 +6330,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, * to stand against the temptation 8) --ANK */ inet_csk_schedule_ack(sk); - tcp_enter_quickack_mode(sk, TCP_MAX_QUICKACKS); + icsk->icsk_ack.lrcvtime = tcp_time_stamp; + tcp_enter_quickack_mode(sk); inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, TCP_DELACK_MAX, TCP_RTO_MAX); @@ -6576,17 +6540,13 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) /* step 5: check the ACK field */ acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH | - FLAG_UPDATE_TS_RECENT | - FLAG_NO_CHALLENGE_ACK) > 0; + FLAG_UPDATE_TS_RECENT) > 0; - if (!acceptable) { - if (sk->sk_state == TCP_SYN_RECV) - return 1; /* send one RST */ - tcp_send_challenge_ack(sk, skb); - goto discard; - } switch (sk->sk_state) { case TCP_SYN_RECV: + if (!acceptable) + return 1; + if (!tp->srtt_us) tcp_synack_rtt_meas(sk, req); @@ -6671,6 +6631,14 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) * our SYNACK so stop the SYNACK timer. */ if (req) { + /* Return RST if ack_seq is invalid. + * Note that RFC793 only says to generate a + * DUPACK for it but for TCP Fast Open it seems + * better to treat this case like TCP_SYN_RECV + * above. + */ + if (!acceptable) + return 1; /* We no longer need the request sock. */ reqsk_fastopen_remove(sk, req, false); tcp_rearm_rto(sk); @@ -6891,7 +6859,7 @@ struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops, struct inet_request_sock *ireq = inet_rsk(req); kmemcheck_annotate_bitfield(ireq, flags); - ireq->ireq_opt = NULL; + ireq->opt = NULL; atomic64_set(&ireq->ir_cookie, 0); ireq->ireq_state = TCP_NEW_SYN_RECV; write_pnet(&ireq->ireq_net, sock_net(sk_listener)); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index aa01be73849e..66e86160f468 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -275,13 +275,10 @@ EXPORT_SYMBOL(tcp_v4_connect); */ void tcp_v4_mtu_reduced(struct sock *sk) { - struct inet_sock *inet = inet_sk(sk); struct dst_entry *dst; - u32 mtu; + struct inet_sock *inet = inet_sk(sk); + u32 mtu = tcp_sk(sk)->mtu_info; - if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) - return; - mtu = tcp_sk(sk)->mtu_info; dst = inet_csk_update_pmtu(sk, mtu); if (!dst) return; @@ -446,8 +443,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) switch (type) { case ICMP_REDIRECT: - if (!sock_owned_by_user(sk)) - do_redirect(icmp_skb, sk); + do_redirect(icmp_skb, sk); goto out; case ICMP_SOURCE_QUENCH: /* Just silently ignore these. */ @@ -926,7 +922,7 @@ void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, tcp_time_stamp, req->ts_recent, 0, - tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->saddr, + tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr, AF_INET), inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0, ip_hdr(skb)->tos @@ -966,7 +962,7 @@ int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst, err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr, ireq->ir_rmt_addr, - ireq_opt_deref(ireq)); + ireq->opt); err = net_xmit_eval(err); } @@ -981,7 +977,7 @@ static #endif void tcp_v4_reqsk_destructor(struct request_sock *req) { - kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1)); + kfree(inet_rsk(req)->opt); } @@ -1315,7 +1311,7 @@ static void tcp_v4_init_req(struct request_sock *req, sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr); sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr); ireq->no_srccheck = inet_sk(sk_listener)->transparent; - RCU_INIT_POINTER(ireq->ireq_opt, tcp_v4_save_options(skb)); + ireq->opt = tcp_v4_save_options(skb); #ifdef CONFIG_MPTCP return 0; @@ -1417,9 +1413,10 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, ireq = inet_rsk(req); sk_daddr_set(newsk, ireq->ir_rmt_addr); sk_rcv_saddr_set(newsk, ireq->ir_loc_addr); - newinet->inet_saddr = ireq->ir_loc_addr; - inet_opt = rcu_dereference(ireq->ireq_opt); - RCU_INIT_POINTER(newinet->inet_opt, inet_opt); + newinet->inet_saddr = ireq->ir_loc_addr; + inet_opt = ireq->opt; + rcu_assign_pointer(newinet->inet_opt, inet_opt); + ireq->opt = NULL; newinet->mc_index = inet_iif(skb); newinet->mc_ttl = ip_hdr(skb)->ttl; newinet->rcv_tos = ip_hdr(skb)->tos; @@ -1467,12 +1464,9 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, if (__inet_inherit_port(sk, newsk) < 0) goto put_and_exit; *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash)); - if (likely(*own_req)) { + if (*own_req) tcp_move_syn(newtp, req); - ireq->ireq_opt = NULL; - } else { - newinet->inet_opt = NULL; - } + return newsk; exit_overflow: @@ -1483,7 +1477,6 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; put_and_exit: - newinet->inet_opt = NULL; inet_csk_prepare_forced_close(newsk); tcp_done(newsk); goto exit; @@ -1676,21 +1669,6 @@ bool tcp_prequeue(struct sock *sk, struct sk_buff *skb) } EXPORT_SYMBOL(tcp_prequeue); -int tcp_filter(struct sock *sk, struct sk_buff *skb) -{ - struct tcphdr *th = (struct tcphdr *)skb->data; - unsigned int eaten = skb->len; - int err; - - err = sk_filter_trim_cap(sk, skb, th->doff * 4); - if (!err) { - eaten -= skb->len; - TCP_SKB_CB(skb)->end_seq -= eaten; - } - return err; -} -EXPORT_SYMBOL(tcp_filter); - /* * From tcp_input.c */ @@ -1809,10 +1787,6 @@ int tcp_v4_rcv(struct sk_buff *skb) reqsk_put(req); goto discard_it; } - if (tcp_checksum_complete(skb)) { - reqsk_put(req); - goto csum_error; - } if (unlikely(sk->sk_state != TCP_LISTEN #ifdef CONFIG_MPTCP && !is_meta_sk(sk) @@ -1882,10 +1856,8 @@ int tcp_v4_rcv(struct sk_buff *skb) nf_reset(skb); - if (tcp_filter(sk, skb)) + if (sk_filter(sk, skb)) goto discard_and_relse; - th = (const struct tcphdr *)skb->data; - iph = ip_hdr(skb); skb->dev = NULL; diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c index 3861dedd5365..1e70fa8fa793 100644 --- a/net/ipv4/tcp_lp.c +++ b/net/ipv4/tcp_lp.c @@ -264,15 +264,13 @@ static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked, s32 rtt_us) { struct tcp_sock *tp = tcp_sk(sk); struct lp *lp = inet_csk_ca(sk); - u32 delta; if (rtt_us > 0) tcp_lp_rtt_sample(sk, rtt_us); /* calc inference */ - delta = tcp_time_stamp - tp->rx_opt.rcv_tsecr; - if ((s32)delta > 0) - lp->inference = 3 * delta; + if (tcp_time_stamp > tp->rx_opt.rcv_tsecr) + lp->inference = 3 * (tcp_time_stamp - tp->rx_opt.rcv_tsecr); /* test if within inference */ if (lp->last_drop && (tcp_time_stamp - lp->last_drop < lp->inference)) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 7b8e9a8072d5..90d0d813b858 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -539,7 +539,6 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, newtp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT); newtp->rtt_min[0].rtt = ~0U; newicsk->icsk_rto = TCP_TIMEOUT_INIT; - newicsk->icsk_ack.lrcvtime = tcp_time_stamp; newtp->packets_out = 0; newtp->retrans_out = 0; @@ -618,7 +617,6 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; newtp->rx_opt.mss_clamp = req->mss; tcp_ecn_openreq_child(newtp, req); - newtp->fastopen_req = NULL; newtp->fastopen_rsk = NULL; newtp->syn_data_acked = 0; newtp->rack.mstamp.v64 = 0; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3303de4734fa..61f75c8bd66b 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -195,13 +195,8 @@ static void tcp_event_data_sent(struct tcp_sock *tp, } /* Account for an ACK we sent. */ -static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts, - u32 rcv_nxt) +static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts) { - struct tcp_sock *tp = tcp_sk(sk); - - if (unlikely(rcv_nxt != tp->rcv_nxt)) - return; /* Special ACK sent by DCTCP to reflect ECN */ tcp_dec_quickack_mode(sk, pkts); inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); } @@ -266,8 +261,7 @@ void tcp_select_initial_window(int __space, __u32 mss, /* Set window scaling on max possible window * See RFC1323 for an explanation of the limit to 14 */ - space = max_t(u32, space, sysctl_tcp_rmem[2]); - space = max_t(u32, space, sysctl_rmem_max); + space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max); space = min_t(u32, space, *window_clamp); while (space > 65535 && (*rcv_wscale) < 14) { space >>= 1; @@ -1026,8 +1020,8 @@ void tcp_wfree(struct sk_buff *skb) #ifndef CONFIG_MPTCP static #endif -int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, - int clone_it, gfp_t gfp_mask, u32 rcv_nxt) +int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, + gfp_t gfp_mask) { const struct inet_connection_sock *icsk = inet_csk(sk); struct inet_sock *inet; @@ -1087,7 +1081,7 @@ int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, th->source = inet->inet_sport; th->dest = inet->inet_dport; th->seq = htonl(tcb->seq); - th->ack_seq = htonl(rcv_nxt); + th->ack_seq = htonl(tp->rcv_nxt); *(((__be16 *)th) + 6) = htons(((tcp_header_size >> 2) << 12) | tcb->tcp_flags); @@ -1138,7 +1132,7 @@ int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, icsk->icsk_af_ops->send_check(sk, skb); if (likely(tcb->tcp_flags & TCPHDR_ACK)) - tcp_event_ack_sent(sk, tcp_skb_pcount(skb), rcv_nxt); + tcp_event_ack_sent(sk, tcp_skb_pcount(skb)); if (skb->len != tcp_header_size) tcp_event_data_sent(tp, sk); @@ -1169,16 +1163,6 @@ int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, return net_xmit_eval(err); } -#ifndef CONFIG_MPTCP -static -#endif -int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, - gfp_t gfp_mask) -{ - return __tcp_transmit_skb(sk, skb, clone_it, gfp_mask, - tcp_sk(sk)->rcv_nxt); -} - /* This routine just queues the buffer for sending. * * NOTE: probe0 timer is not checked, do not forget tcp_push_pending_frames, @@ -1376,7 +1360,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, #ifndef CONFIG_MPTCP static #endif -int __pskb_trim_head(struct sk_buff *skb, int len) +void __pskb_trim_head(struct sk_buff *skb, int len) { struct skb_shared_info *shinfo; int i, k, eat; @@ -1386,7 +1370,7 @@ int __pskb_trim_head(struct sk_buff *skb, int len) __skb_pull(skb, eat); len -= eat; if (!len) - return 0; + return; } eat = len; k = 0; @@ -1412,28 +1396,23 @@ int __pskb_trim_head(struct sk_buff *skb, int len) skb_reset_tail_pointer(skb); skb->data_len -= len; skb->len = skb->data_len; - return len; } /* Remove acked data from a packet in the transmit queue. */ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) { - u32 delta_truesize; - if (skb_unclone(skb, GFP_ATOMIC)) return -ENOMEM; - delta_truesize = __pskb_trim_head(skb, len); + __pskb_trim_head(skb, len); TCP_SKB_CB(skb)->seq += len; skb->ip_summed = CHECKSUM_PARTIAL; - if (delta_truesize) { - skb->truesize -= delta_truesize; - sk->sk_wmem_queued -= delta_truesize; - sk_mem_uncharge(sk, delta_truesize); - sock_set_flag(sk, SOCK_QUEUE_SHRUNK); - } + skb->truesize -= len; + sk->sk_wmem_queued -= len; + sk_mem_uncharge(sk, len); + sock_set_flag(sk, SOCK_QUEUE_SHRUNK); /* Any change of skb->len requires recalculation of tso factor. */ if (tcp_skb_pcount(skb) > 1) @@ -2142,19 +2121,16 @@ static int tcp_mtu_probe(struct sock *sk) nskb->ip_summed = skb->ip_summed; tcp_insert_write_queue_before(nskb, skb, sk); - tcp_highest_sack_replace(sk, skb, nskb); len = 0; tcp_for_write_queue_from_safe(skb, next, sk) { copy = min_t(int, skb->len, probe_size - len); - if (nskb->ip_summed) { + if (nskb->ip_summed) skb_copy_bits(skb, 0, skb_put(nskb, copy), copy); - } else { - __wsum csum = skb_copy_and_csum_bits(skb, 0, - skb_put(nskb, copy), - copy, 0); - nskb->csum = csum_block_add(nskb->csum, csum, len); - } + else + nskb->csum = skb_copy_and_csum_bits(skb, 0, + skb_put(nskb, copy), + copy, nskb->csum); if (skb->len <= copy) { /* We've eaten all the data from this skb. @@ -2615,11 +2591,9 @@ u32 __tcp_select_window(struct sock *sk) int full_space = min_t(int, tp->window_clamp, allowed_space); int window; - if (unlikely(mss > full_space)) { + if (mss > full_space) mss = full_space; - if (mss <= 0) - return 0; - } + if (free_space < (full_space >> 1)) { icsk->icsk_ack.quick = 0; @@ -2691,7 +2665,7 @@ static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb) BUG_ON(tcp_skb_pcount(skb) != 1 || tcp_skb_pcount(next_skb) != 1); - tcp_highest_sack_replace(sk, next_skb, skb); + tcp_highest_sack_combine(sk, next_skb, skb); tcp_unlink_write_queue(next_skb, sk); @@ -2811,18 +2785,15 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) * copying overhead: fragmentation, tunneling, mangling etc. */ if (atomic_read(&sk->sk_wmem_alloc) > - min_t(u32, sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2), - sk->sk_sndbuf)) + min(sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2), sk->sk_sndbuf)) return -EAGAIN; if (skb_still_in_host_queue(sk, skb)) return -EBUSY; if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) { - if (unlikely(before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))) { - WARN_ON_ONCE(1); - return -EINVAL; - } + if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una)) + BUG(); if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq)) return -ENOMEM; } @@ -3252,8 +3223,13 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, tcp_ecn_make_synack(req, th); th->source = htons(ireq->ir_num); th->dest = ireq->ir_rmt_port; - skb->ip_summed = CHECKSUM_PARTIAL; - th->seq = htonl(tcp_rsk(req)->snt_isn); + /* Setting of flags are superfluous here for callers (and ECE is + * not even correctly set) + */ + tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn, + TCPHDR_SYN | TCPHDR_ACK); + + th->seq = htonl(TCP_SKB_CB(skb)->seq); /* XXX data is queued and acked as is. No buffer/window check */ th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt); @@ -3365,7 +3341,6 @@ static void tcp_connect_init(struct sock *sk) sock_reset_flag(sk, SOCK_DONE); tp->snd_wnd = 0; tcp_init_wl(tp, 0); - tcp_write_queue_purge(sk); tp->snd_una = tp->write_seq; tp->snd_sml = tp->write_seq; tp->snd_up = tp->write_seq; @@ -3531,9 +3506,6 @@ int tcp_connect(struct sock *sk) struct sk_buff *buff; int err; - if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk)) - return -EHOSTUNREACH; /* Routing failure or similar. */ - tcp_connect_init(sk); if (unlikely(tp->repair)) { @@ -3580,6 +3552,8 @@ void tcp_send_delayed_ack(struct sock *sk) int ato = icsk->icsk_ack.ato; unsigned long timeout; + tcp_ca_event(sk, CA_EVENT_DELAYED_ACK); + if (ato > TCP_DELACK_MIN) { const struct tcp_sock *tp = tcp_sk(sk); int max_ato = HZ / 2; @@ -3628,7 +3602,7 @@ void tcp_send_delayed_ack(struct sock *sk) } /* This routine sends an ack and also updates the window. */ -void __tcp_send_ack(struct sock *sk, u32 rcv_nxt) +void tcp_send_ack(struct sock *sk) { struct sk_buff *buff; @@ -3636,6 +3610,8 @@ void __tcp_send_ack(struct sock *sk, u32 rcv_nxt) if (sk->sk_state == TCP_CLOSE) return; + tcp_ca_event(sk, CA_EVENT_NON_DELAYED_ACK); + /* We are not putting this on the write queue, so * tcp_transmit_skb() will set the ownership to this * sock. @@ -3663,14 +3639,9 @@ void __tcp_send_ack(struct sock *sk, u32 rcv_nxt) /* Send it off, this clears delayed acks for us. */ skb_mstamp_get(&buff->skb_mstamp); - __tcp_transmit_skb(sk, buff, 0, sk_gfp_atomic(sk, GFP_ATOMIC), rcv_nxt); -} -EXPORT_SYMBOL_GPL(__tcp_send_ack); - -void tcp_send_ack(struct sock *sk) -{ - __tcp_send_ack(sk, tcp_sk(sk)->rcv_nxt); + tcp_transmit_skb(sk, buff, 0, sk_gfp_atomic(sk, GFP_ATOMIC)); } +EXPORT_SYMBOL_GPL(tcp_send_ack); /* This routine sends a packet with an out of date sequence * number. It assumes the other end will try to ack it. diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index d7d7b00c286a..4550a0bc1a5c 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -52,19 +52,11 @@ void tcp_write_err(struct sock *sk) * to prevent DoS attacks. It is called when a retransmission timeout * or zero probe timeout occurs on orphaned socket. * - * Also close if our net namespace is exiting; in that case there is no - * hope of ever communicating again since all netns interfaces are already - * down (or about to be down), and we need to release our dst references, - * which have been moved to the netns loopback interface, so the namespace - * can finish exiting. This condition is only possible if we are a kernel - * socket, as those do not hold references to the namespace. - * * Criteria is still not confirmed experimentally and may change. * We kill the socket, if: * 1. If number of orphaned sockets exceeds an administratively configured * limit. * 2. If we have strong memory pressure. - * 3. If our net namespace is exiting. */ static int tcp_out_of_resources(struct sock *sk, bool do_reset) { @@ -97,13 +89,6 @@ static int tcp_out_of_resources(struct sock *sk, bool do_reset) NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY); return 1; } - - if (!check_net(sock_net(sk))) { - /* Not possible to send reset; just close */ - tcp_done(sk); - return 1; - } - return 0; } @@ -264,8 +249,7 @@ void tcp_delack_timer_handler(struct sock *sk) sk_mem_reclaim_partial(sk); - if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) || - !(icsk->icsk_ack.pending & ICSK_ACK_TIMER)) + if (sk->sk_state == TCP_CLOSE || !(icsk->icsk_ack.pending & ICSK_ACK_TIMER)) goto out; if (time_after(icsk->icsk_ack.timeout, jiffies)) { @@ -565,8 +549,7 @@ void tcp_write_timer_handler(struct sock *sk) struct inet_connection_sock *icsk = inet_csk(sk); int event; - if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) || - !icsk->icsk_pending) + if (sk->sk_state == TCP_CLOSE || !icsk->icsk_pending) goto out; if (time_after(icsk->icsk_timeout, jiffies)) { @@ -723,8 +706,7 @@ static void tcp_keepalive_timer (unsigned long data) goto death; } - if (!sock_flag(sk, SOCK_KEEPOPEN) || - ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT))) + if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE) goto out; elapsed = keepalive_time_when(tp); diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c index b9fac0522be6..13951c4087d4 100644 --- a/net/ipv4/tcp_vegas.c +++ b/net/ipv4/tcp_vegas.c @@ -158,7 +158,7 @@ EXPORT_SYMBOL_GPL(tcp_vegas_cwnd_event); static inline u32 tcp_vegas_ssthresh(struct tcp_sock *tp) { - return min(tp->snd_ssthresh, tp->snd_cwnd); + return min(tp->snd_ssthresh, tp->snd_cwnd-1); } static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 acked) diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c index 92ab5bc91592..3e6a472e6b88 100644 --- a/net/ipv4/tcp_yeah.c +++ b/net/ipv4/tcp_yeah.c @@ -75,7 +75,7 @@ static void tcp_yeah_cong_avoid(struct sock *sk, u32 ack, u32 acked) if (!tcp_is_cwnd_limited(sk)) return; - if (tcp_in_slow_start(tp)) + if (tp->snd_cwnd <= tp->snd_ssthresh) tcp_slow_start(tp, acked); else if (!yeah->doing_reno_now) { diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 23bf90e5e47a..64241997605d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -991,10 +991,8 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) ipc.addr = faddr = daddr; if (ipc.opt && ipc.opt->opt.srr) { - if (!daddr) { - err = -EINVAL; - goto out_free; - } + if (!daddr) + return -EINVAL; faddr = ipc.opt->opt.faddr; connected = 0; } @@ -1108,7 +1106,6 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) out: ip_rt_put(rt); -out_free: if (free) kfree(ipc.opt); if (!err) @@ -1346,7 +1343,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, *addr_len = sizeof(*sin); } if (inet->cmsg_flags) - ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr), off); + ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr)); err = copied; if (flags & MSG_TRUNC) @@ -1537,7 +1534,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) /* if we're overly short, let UDP handle it */ encap_rcv = ACCESS_ONCE(up->encap_rcv); - if (encap_rcv) { + if (skb->len > sizeof(struct udphdr) && encap_rcv) { int ret; /* Verify checksum before giving to encap */ @@ -1748,11 +1745,6 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh, err = udplite_checksum_init(skb, uh); if (err) return err; - - if (UDP_SKB_CB(skb)->partial_cov) { - skb->csum = inet_compute_pseudo(skb, proto); - return 0; - } } return skb_checksum_init_zero_check(skb, proto, uh->check, diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 6dfc3daf7c21..0e36e56dfd22 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -231,7 +231,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, if (uh->check == 0) uh->check = CSUM_MANGLED_0; - skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->ip_summed = CHECKSUM_NONE; /* Fragment the skb. IP headers of the fragments are updated in * inet_gso_segment() @@ -339,8 +339,8 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, skb_gro_pull(skb, sizeof(struct udphdr)); /* pull encapsulating udp header */ skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr)); NAPI_GRO_CB(skb)->proto = uo_priv->offload->ipproto; - pp = call_gro_receive_udp(uo_priv->offload->callbacks.gro_receive, - head, skb, uo_priv->offload); + pp = uo_priv->offload->callbacks.gro_receive(head, skb, + uo_priv->offload); out_unlock: rcu_read_unlock(); diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index fddae0164b91..7b0edb37a115 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -97,7 +97,6 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, xdst->u.rt.rt_gateway = rt->rt_gateway; xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway; xdst->u.rt.rt_pmtu = rt->rt_pmtu; - xdst->u.rt.rt_mtu_locked = rt->rt_mtu_locked; xdst->u.rt.rt_table_id = rt->rt_table_id; INIT_LIST_HEAD(&xdst->u.rt.rt_uncached); diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 0f50248bad17..983bb999738c 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -69,7 +69,6 @@ config INET6_ESP select CRYPTO_CBC select CRYPTO_SHA1 select CRYPTO_DES - select CRYPTO_ECHAINIV ---help--- Support for IPsec ESP. @@ -206,7 +205,6 @@ config IPV6_NDISC_NODETYPE config IPV6_TUNNEL tristate "IPv6: IP-in-IPv6 tunnel (RFC2473)" select INET6_TUNNEL - select DST_CACHE ---help--- Support for IPv6-in-IPv6 and IPv4-in-IPv6 tunnels described in RFC 2473. diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 5ece422275c5..8fc0d8f46666 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -318,9 +318,9 @@ static void addrconf_mod_rs_timer(struct inet6_dev *idev, static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp, unsigned long delay) { - in6_ifa_hold(ifp); - if (mod_delayed_work(addrconf_wq, &ifp->dad_work, delay)) - in6_ifa_put(ifp); + if (!delayed_work_pending(&ifp->dad_work)) + in6_ifa_hold(ifp); + mod_delayed_work(addrconf_wq, &ifp->dad_work, delay); } static int snmp6_alloc_dev(struct inet6_dev *idev) @@ -987,10 +987,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, INIT_HLIST_NODE(&ifa->addr_lst); ifa->scope = scope; ifa->prefix_len = pfxlen; - ifa->flags = flags; - /* No need to add the TENTATIVE flag for addresses with NODAD */ - if (!(flags & IFA_F_NODAD)) - ifa->flags |= IFA_F_TENTATIVE; + ifa->flags = flags | IFA_F_TENTATIVE; ifa->valid_lft = valid_lft; ifa->prefered_lft = prefered_lft; ifa->cstamp = ifa->tstamp = jiffies; @@ -1805,7 +1802,17 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) { - if (ifp->flags&IFA_F_TEMPORARY) { + if (ifp->flags&IFA_F_PERMANENT) { + spin_lock_bh(&ifp->lock); + addrconf_del_dad_work(ifp); + ifp->flags |= IFA_F_TENTATIVE; + if (dad_failed) + ifp->flags |= IFA_F_DADFAILED; + spin_unlock_bh(&ifp->lock); + if (dad_failed) + ipv6_ifa_notify(0, ifp); + in6_ifa_put(ifp); + } else if (ifp->flags&IFA_F_TEMPORARY) { struct inet6_ifaddr *ifpub; spin_lock_bh(&ifp->lock); ifpub = ifp->ifpub; @@ -1818,16 +1825,6 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) spin_unlock_bh(&ifp->lock); } ipv6_del_addr(ifp); - } else if (ifp->flags&IFA_F_PERMANENT || !dad_failed) { - spin_lock_bh(&ifp->lock); - addrconf_del_dad_work(ifp); - ifp->flags |= IFA_F_TENTATIVE; - if (dad_failed) - ifp->flags |= IFA_F_DADFAILED; - spin_unlock_bh(&ifp->lock); - if (dad_failed) - ipv6_ifa_notify(0, ifp); - in6_ifa_put(ifp); } else { ipv6_del_addr(ifp); } @@ -1931,7 +1928,6 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) spin_unlock_bh(&ifp->lock); addrconf_mod_dad_work(ifp, 0); - in6_ifa_put(ifp); } /* Join to solicited addr multicast group. @@ -2984,7 +2980,7 @@ static void init_loopback(struct net_device *dev) * lo device down, release this obsolete dst and * reallocate a new router for ifa. */ - if (!atomic_read(&sp_ifa->rt->rt6i_ref)) { + if (sp_ifa->rt->dst.obsolete > 0) { ip6_rt_put(sp_ifa->rt); sp_ifa->rt = NULL; } else { @@ -3212,7 +3208,6 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct inet6_dev *idev = __in6_dev_get(dev); - struct net *net = dev_net(dev); int run_pending = 0; int err; @@ -3228,7 +3223,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, case NETDEV_CHANGEMTU: /* if MTU under IPV6_MIN_MTU stop IPv6 on this interface. */ if (dev->mtu < IPV6_MIN_MTU) { - addrconf_ifdown(dev, dev != net->loopback_dev); + addrconf_ifdown(dev, 1); break; } @@ -3281,15 +3276,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, } if (idev) { - if (idev->if_flags & IF_READY) { - /* device is already configured - - * but resend MLD reports, we might - * have roamed and need to update - * multicast snooping switches - */ - ipv6_mc_up(idev); + if (idev->if_flags & IF_READY) + /* device is already configured. */ break; - } idev->if_flags |= IF_READY; } @@ -3341,7 +3330,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, * IPV6_MIN_MTU stop IPv6 on this interface. */ if (dev->mtu < IPV6_MIN_MTU) - addrconf_ifdown(dev, dev != net->loopback_dev); + addrconf_ifdown(dev, 1); } break; @@ -3382,7 +3371,6 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, */ static struct notifier_block ipv6_dev_notf = { .notifier_call = addrconf_notify, - .priority = ADDRCONF_NOTIFY_PRIORITY, }; static void addrconf_type_change(struct net_device *dev, unsigned long event) @@ -3689,7 +3677,6 @@ static void addrconf_dad_work(struct work_struct *w) addrconf_dad_begin(ifp); goto out; } else if (action == DAD_ABORT) { - in6_ifa_hold(ifp); addrconf_dad_stop(ifp, 1); goto out; } @@ -5230,7 +5217,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) * our DAD process, so we don't need * to do it again */ - if (!rcu_access_pointer(ifp->rt->rt6i_node)) + if (!(ifp->rt->rt6i_node)) ip6_ins_rt(ifp->rt); if (ifp->idev->cnf.forwarding) addrconf_join_anycast(ifp); @@ -5330,7 +5317,8 @@ static void addrconf_disable_change(struct net *net, __s32 newf) struct net_device *dev; struct inet6_dev *idev; - for_each_netdev(net, dev) { + rcu_read_lock(); + for_each_netdev_rcu(net, dev) { idev = __in6_dev_get(dev); if (idev) { int changed = (!idev->cnf.disable_ipv6) ^ (!newf); @@ -5339,6 +5327,7 @@ static void addrconf_disable_change(struct net *net, __s32 newf) dev_disable_change(idev); } } + rcu_read_unlock(); } static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf) @@ -6047,8 +6036,6 @@ int __init addrconf_init(void) goto errlo; } - ip6_route_init_special_entries(); - for (i = 0; i < IN6_ADDR_HSIZE; i++) INIT_HLIST_HEAD(&inet6_addr_lst[i]); diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index d85a56b98a83..86359bf1507d 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -219,6 +219,7 @@ int inet6_create(struct net *net, struct socket *sock, int protocol, np->mcast_hops = IPV6_DEFAULT_MCASTHOPS; np->mc_loop = 1; np->pmtudisc = IPV6_PMTUDISC_WANT; + np->autoflowlabel = ip6_default_np_autolabel(sock_net(sk)); sk->sk_ipv6only = net->ipv6.sysctl.bindv6only; /* Init the ipv4 part of the socket since we can have sockets @@ -912,12 +913,12 @@ static int __init inet6_init(void) err = register_pernet_subsys(&inet6_net_ops); if (err) goto register_pernet_fail; - err = ip6_mr_init(); - if (err) - goto ipmr_fail; err = icmpv6_init(); if (err) goto icmp_fail; + err = ip6_mr_init(); + if (err) + goto ipmr_fail; err = ndisc_init(); if (err) goto ndisc_fail; @@ -1035,10 +1036,10 @@ static int __init inet6_init(void) ndisc_cleanup(); ndisc_fail: ip6_mr_cleanup(); -icmp_fail: - unregister_pernet_subsys(&inet6_net_ops); ipmr_fail: icmpv6_cleanup(); +icmp_fail: + unregister_pernet_subsys(&inet6_net_ops); register_pernet_fail: sock_unregister(PF_INET6); rtnl_unregister_all(PF_INET6); diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index e742c4deb13d..189eb10b742d 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -423,9 +423,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); sg_init_table(sg, nfrags + sglists); - err = skb_to_sgvec_nomark(skb, sg, 0, skb->len); - if (unlikely(err < 0)) - goto out_free; + skb_to_sgvec_nomark(skb, sg, 0, skb->len); if (x->props.flags & XFRM_STATE_ESN) { /* Attach seqhi sg right after packet payload */ @@ -605,9 +603,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) ip6h->hop_limit = 0; sg_init_table(sg, nfrags + sglists); - err = skb_to_sgvec_nomark(skb, sg, 0, skb->len); - if (unlikely(err < 0)) - goto out_free; + skb_to_sgvec_nomark(skb, sg, 0, skb->len); if (x->props.flags & XFRM_STATE_ESN) { /* Attach seqhi sg right after packet payload */ diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index fc69e03451a7..cf2dfb222230 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -76,22 +76,18 @@ static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int a } } - if (ipv6_addr_any(&usin->sin6_addr)) { + addr_type = ipv6_addr_type(&usin->sin6_addr); + + if (addr_type == IPV6_ADDR_ANY) { /* * connect to self */ - if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) - ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK), - &usin->sin6_addr); - else - usin->sin6_addr = in6addr_loopback; + usin->sin6_addr.s6_addr[15] = 0x01; } - addr_type = ipv6_addr_type(&usin->sin6_addr); - daddr = &usin->sin6_addr; - if (addr_type & IPV6_ADDR_MAPPED) { + if (addr_type == IPV6_ADDR_MAPPED) { struct sockaddr_in sin; if (__ipv6_only_sock(sk)) { @@ -658,16 +654,13 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg, } if (np->rxopt.bits.rxorigdstaddr) { struct sockaddr_in6 sin6; - __be16 *ports; - int end; + __be16 *ports = (__be16 *) skb_transport_header(skb); - end = skb_transport_offset(skb) + 4; - if (end <= 0 || pskb_may_pull(skb, end)) { + if (skb_transport_offset(skb) + 4 <= skb->len) { /* All current transport protocols have the port numbers in the * first four bytes of the transport header and this function is * written with this assumption in mind. */ - ports = (__be16 *)skb_transport_header(skb); sin6.sin6_family = AF_INET6; sin6.sin6_addr = ipv6_hdr(skb)->daddr; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 44a2010e2076..218f0cba231c 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -248,11 +248,9 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) esph->spi = x->id.spi; sg_init_table(sg, nfrags); - err = skb_to_sgvec(skb, sg, - (unsigned char *)esph - skb->data, - assoclen + ivlen + clen + alen); - if (unlikely(err < 0)) - goto error; + skb_to_sgvec(skb, sg, + (unsigned char *)esph - skb->data, + assoclen + ivlen + clen + alen); aead_request_set_crypt(req, sg, sg, ivlen + clen, iv); aead_request_set_ad(req, assoclen); @@ -420,14 +418,12 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) esph = (void *)skb_push(skb, 4); *seqhi = esph->spi; esph->spi = esph->seq_no; - esph->seq_no = XFRM_SKB_CB(skb)->seq.input.hi; + esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.input.hi); aead_request_set_callback(req, 0, esp_input_done_esn, skb); } sg_init_table(sg, nfrags); - ret = skb_to_sgvec(skb, sg, 0, skb->len); - if (unlikely(ret < 0)) - goto out; + skb_to_sgvec(skb, sg, 0, skb->len); aead_request_set_crypt(req, sg, sg, elen + ivlen, iv); aead_request_set_ad(req, assoclen); diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 9ac4f0cef27d..ed33abf57abd 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -32,6 +32,7 @@ struct fib6_rule { struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, int flags, pol_lookup_t lookup) { + struct rt6_info *rt; struct fib_lookup_arg arg = { .lookup_ptr = lookup, .flags = FIB_LOOKUP_NOREF, @@ -40,11 +41,21 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, fib_rules_lookup(net->ipv6.fib6_rules_ops, flowi6_to_flowi(fl6), flags, &arg); - if (arg.result) - return arg.result; + rt = arg.result; - dst_hold(&net->ipv6.ip6_null_entry->dst); - return &net->ipv6.ip6_null_entry->dst; + if (!rt) { + dst_hold(&net->ipv6.ip6_null_entry->dst); + return &net->ipv6.ip6_null_entry->dst; + } + + if (rt->rt6i_flags & RTF_REJECT && + rt->dst.error == -EAGAIN) { + ip6_rt_put(rt); + rt = net->ipv6.ip6_null_entry; + dst_hold(&rt->dst); + } + + return &rt->dst; } static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, @@ -105,8 +116,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, flp6->saddr = saddr; } err = rt->dst.error; - if (err != -EAGAIN) - goto out; + goto out; } again: ip6_rt_put(rt); diff --git a/net/ipv6/ip6_checksum.c b/net/ipv6/ip6_checksum.c index 391a8fedb27e..9a4d7322fb22 100644 --- a/net/ipv6/ip6_checksum.c +++ b/net/ipv6/ip6_checksum.c @@ -73,11 +73,6 @@ int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto) err = udplite_checksum_init(skb, uh); if (err) return err; - - if (UDP_SKB_CB(skb)->partial_cov) { - skb->csum = ip6_compute_pseudo(skb, proto); - return 0; - } } /* To support RFC 6936 (allow zero checksum in UDP/IPV6 for tunnels) diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index c23e02a7ccb0..0c7e276c230e 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -150,21 +150,9 @@ static struct fib6_node *node_alloc(void) return fn; } -static void node_free_immediate(struct fib6_node *fn) -{ - kmem_cache_free(fib6_node_kmem, fn); -} - -static void node_free_rcu(struct rcu_head *head) -{ - struct fib6_node *fn = container_of(head, struct fib6_node, rcu); - - kmem_cache_free(fib6_node_kmem, fn); -} - static void node_free(struct fib6_node *fn) { - call_rcu(&fn->rcu, node_free_rcu); + kmem_cache_free(fib6_node_kmem, fn); } static void rt6_rcu_free(struct rt6_info *rt) @@ -191,7 +179,6 @@ static void rt6_free_pcpu(struct rt6_info *non_pcpu_rt) } } - free_percpu(non_pcpu_rt->rt6i_pcpu); non_pcpu_rt->rt6i_pcpu = NULL; } @@ -203,12 +190,6 @@ static void rt6_release(struct rt6_info *rt) } } -static void fib6_free_table(struct fib6_table *table) -{ - inetpeer_invalidate_tree(&table->tb6_peers); - kfree(table); -} - static void fib6_link_table(struct net *net, struct fib6_table *tb) { unsigned int h; @@ -308,7 +289,8 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, struct rt6_info *rt; rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags); - if (rt->dst.error == -EAGAIN) { + if (rt->rt6i_flags & RTF_REJECT && + rt->dst.error == -EAGAIN) { ip6_rt_put(rt); rt = net->ipv6.ip6_null_entry; dst_hold(&rt->dst); @@ -606,9 +588,9 @@ static struct fib6_node *fib6_add_1(struct fib6_node *root, if (!in || !ln) { if (in) - node_free_immediate(in); + node_free(in); if (ln) - node_free_immediate(ln); + node_free(ln); return ERR_PTR(-ENOMEM); } @@ -785,7 +767,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, goto next_iter; } - if (rt6_duplicate_nexthop(iter, rt)) { + if (iter->dst.dev == rt->dst.dev && + iter->rt6i_idev == rt->rt6i_idev && + ipv6_addr_equal(&iter->rt6i_gateway, + &rt->rt6i_gateway)) { if (rt->rt6i_nsiblings) rt->rt6i_nsiblings = 0; if (!(iter->rt6i_flags & RTF_EXPIRES)) @@ -875,7 +860,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, rt->dst.rt6_next = iter; *ins = rt; - rcu_assign_pointer(rt->rt6i_node, fn); + rt->rt6i_node = fn; atomic_inc(&rt->rt6i_ref); inet6_rt_notify(RTM_NEWROUTE, rt, info, 0); info->nl_net->ipv6.rt6_stats->fib_rt_entries++; @@ -900,7 +885,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, return err; *ins = rt; - rcu_assign_pointer(rt->rt6i_node, fn); + rt->rt6i_node = fn; rt->dst.rt6_next = iter->dst.rt6_next; atomic_inc(&rt->rt6i_ref); inet6_rt_notify(RTM_NEWROUTE, rt, info, NLM_F_REPLACE); @@ -910,8 +895,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, } nsiblings = iter->rt6i_nsiblings; fib6_purge_rt(iter, fn, info->nl_net); - if (fn->rr_ptr == iter) - fn->rr_ptr = NULL; rt6_release(iter); if (nsiblings) { @@ -919,13 +902,9 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, ins = &rt->dst.rt6_next; iter = *ins; while (iter) { - if (iter->rt6i_metric > rt->rt6i_metric) - break; if (rt6_qualify_for_ecmp(iter)) { *ins = iter->dst.rt6_next; fib6_purge_rt(iter, fn, info->nl_net); - if (fn->rr_ptr == iter) - fn->rr_ptr = NULL; rt6_release(iter); nsiblings--; } else { @@ -1014,7 +993,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, /* Create subtree root node */ sfn = node_alloc(); if (!sfn) - goto failure; + goto st_failure; sfn->leaf = info->nl_net->ipv6.ip6_null_entry; atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref); @@ -1030,12 +1009,12 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, if (IS_ERR(sn)) { /* If it is failed, discard just allocated - root, and then (in failure) stale node + root, and then (in st_failure) stale node in main tree. */ - node_free_immediate(sfn); + node_free(sfn); err = PTR_ERR(sn); - goto failure; + goto st_failure; } /* Now link new subtree to main tree */ @@ -1049,7 +1028,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, if (IS_ERR(sn)) { err = PTR_ERR(sn); - goto failure; + goto st_failure; } } @@ -1091,22 +1070,22 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, atomic_inc(&pn->leaf->rt6i_ref); } #endif - goto failure; + if (!(rt->dst.flags & DST_NOCACHE)) + dst_free(&rt->dst); } return err; -failure: - /* fn->leaf could be NULL if fn is an intermediate node and we - * failed to add the new route to it in both subtree creation - * failure and fib6_add_rt2node() failure case. - * In both cases, fib6_repair_tree() should be called to fix - * fn->leaf. +#ifdef CONFIG_IPV6_SUBTREES + /* Subtree creation failed, probably main tree node + is orphan. If it is, shoot it. */ +st_failure: if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) fib6_repair_tree(info->nl_net, fn); if (!(rt->dst.flags & DST_NOCACHE)) dst_free(&rt->dst); return err; +#endif } /* @@ -1460,9 +1439,8 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, int fib6_del(struct rt6_info *rt, struct nl_info *info) { - struct fib6_node *fn = rcu_dereference_protected(rt->rt6i_node, - lockdep_is_held(&rt->rt6i_table->tb6_lock)); struct net *net = info->nl_net; + struct fib6_node *fn = rt->rt6i_node; struct rt6_info **rtp; #if RT6_DEBUG >= 2 @@ -1651,9 +1629,7 @@ static int fib6_clean_node(struct fib6_walker *w) if (res) { #if RT6_DEBUG >= 2 pr_debug("%s: del failed: rt=%p@%p err=%d\n", - __func__, rt, - rcu_access_pointer(rt->rt6i_node), - res); + __func__, rt, rt->rt6i_node, res); #endif continue; } @@ -1891,22 +1867,15 @@ static int __net_init fib6_net_init(struct net *net) static void fib6_net_exit(struct net *net) { - unsigned int i; - rt6_ifdown(net, NULL); del_timer_sync(&net->ipv6.ip6_fib_timer); - for (i = 0; i < FIB6_TABLE_HASHSZ; i++) { - struct hlist_head *head = &net->ipv6.fib_table_hash[i]; - struct hlist_node *tmp; - struct fib6_table *tb; - - hlist_for_each_entry_safe(tb, tmp, head, tb6_hlist) { - hlist_del(&tb->tb6_hlist); - fib6_free_table(tb); - } - } - +#ifdef CONFIG_IPV6_MULTIPLE_TABLES + inetpeer_invalidate_tree(&net->ipv6.fib6_local_tbl->tb6_peers); + kfree(net->ipv6.fib6_local_tbl); +#endif + inetpeer_invalidate_tree(&net->ipv6.fib6_main_tbl->tb6_peers); + kfree(net->ipv6.fib6_main_tbl); kfree(net->ipv6.fib_table_hash); kfree(net->ipv6.rt6_stats); } diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index f3a0a9c0f61e..dc2db4f7b182 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -315,7 +315,6 @@ struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space, } opt_space->dst1opt = fopt->dst1opt; opt_space->opt_flen = fopt->opt_flen; - opt_space->tot_len = fopt->tot_len; return opt_space; } EXPORT_SYMBOL_GPL(fl6_merge_options); diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index d908c0fb1694..78e0e5de912f 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -55,7 +55,6 @@ #include #include #include -#include static bool log_ecn_error = true; @@ -320,13 +319,11 @@ static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net, if (t || !create) return t; - if (parms->name[0]) { - if (!dev_valid_name(parms->name)) - return NULL; + if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); - } else { + else strcpy(name, "ip6gre%d"); - } + dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, ip6gre_tunnel_setup); if (!dev) @@ -364,7 +361,7 @@ static void ip6gre_tunnel_uninit(struct net_device *dev) struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id); ip6gre_tunnel_unlink(ign, t); - dst_cache_reset(&t->dst_cache); + ip6_tnl_dst_reset(t); dev_put(dev); } @@ -411,16 +408,13 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, case ICMPV6_DEST_UNREACH: net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n", t->parms.name); - if (code != ICMPV6_PORT_UNREACH) - break; - return; + break; case ICMPV6_TIME_EXCEED: if (code == ICMPV6_EXC_HOPLIMIT) { net_dbg_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n", t->parms.name); - break; } - return; + break; case ICMPV6_PARAMPROB: teli = 0; if (code == ICMPV6_HDR_FIELD) @@ -436,13 +430,13 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, net_dbg_ratelimited("%s: Recipient unable to parse tunneled packet!\n", t->parms.name); } - return; + break; case ICMPV6_PKT_TOOBIG: mtu = be32_to_cpu(info) - offset; if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; t->dev->mtu = mtu; - return; + break; } if (time_before(jiffies, t->err_time + IP6TUNNEL_ERR_TIMEO)) @@ -642,7 +636,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, } if (!fl6->flowi6_mark) - dst = dst_cache_get(&tunnel->dst_cache); + dst = ip6_tnl_dst_get(tunnel); if (!dst) { dst = ip6_route_output(net, NULL, fl6); @@ -711,7 +705,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, } if (!fl6->flowi6_mark && ndst) - dst_cache_set_ip6(&tunnel->dst_cache, ndst, &fl6->saddr); + ip6_tnl_dst_set(tunnel, ndst); skb_dst_set(skb, dst); proto = NEXTHDR_GRE; @@ -898,6 +892,7 @@ static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev) encap_limit = t->parms.encap_limit; memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); + fl6.flowi6_proto = skb->protocol; err = ip6gre_xmit2(skb, dev, 0, &fl6, encap_limit, &mtu); @@ -1023,7 +1018,7 @@ static int ip6gre_tnl_change(struct ip6_tnl *t, t->parms.o_key = p->o_key; t->parms.i_flags = p->i_flags; t->parms.o_flags = p->o_flags; - dst_cache_reset(&t->dst_cache); + ip6_tnl_dst_reset(t); ip6gre_tnl_link_config(t, set_mtu); return 0; } @@ -1182,25 +1177,24 @@ static int ip6gre_tunnel_change_mtu(struct net_device *dev, int new_mtu) } static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, const void *daddr, - const void *saddr, unsigned int len) + unsigned short type, + const void *daddr, const void *saddr, unsigned int len) { struct ip6_tnl *t = netdev_priv(dev); - struct ipv6hdr *ipv6h; - __be16 *p; + struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen); + __be16 *p = (__be16 *)(ipv6h+1); - ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen + sizeof(*ipv6h)); - ip6_flow_hdr(ipv6h, 0, ip6_make_flowlabel(dev_net(dev), skb, - t->fl.u.ip6.flowlabel, - true, &t->fl.u.ip6)); + ip6_flow_hdr(ipv6h, 0, + ip6_make_flowlabel(dev_net(dev), skb, + t->fl.u.ip6.flowlabel, true, + &t->fl.u.ip6)); ipv6h->hop_limit = t->parms.hop_limit; ipv6h->nexthdr = NEXTHDR_GRE; ipv6h->saddr = t->parms.laddr; ipv6h->daddr = t->parms.raddr; - p = (__be16 *)(ipv6h + 1); - p[0] = t->parms.o_flags; - p[1] = htons(type); + p[0] = t->parms.o_flags; + p[1] = htons(type); /* * Set the source hardware address. @@ -1234,7 +1228,7 @@ static void ip6gre_dev_free(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); - dst_cache_destroy(&t->dst_cache); + ip6_tnl_dst_destroy(t); free_percpu(dev->tstats); free_netdev(dev); } @@ -1272,7 +1266,7 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) if (!dev->tstats) return -ENOMEM; - ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); + ret = ip6_tnl_dst_init(tunnel); if (ret) { free_percpu(dev->tstats); dev->tstats = NULL; diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 9e2ea4ae840d..67316a996820 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -199,7 +199,6 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, ops = rcu_dereference(inet6_offloads[proto]); if (!ops || !ops->callbacks.gro_receive) { __pskb_pull(skb, skb_gro_offset(skb)); - skb_gro_frag0_invalidate(skb); proto = ipv6_gso_pull_exthdrs(skb, proto); skb_gro_pull(skb, -skb_transport_offset(skb)); skb_reset_transport_header(skb); @@ -251,7 +250,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, skb_gro_postpull_rcsum(skb, iph, nlen); - pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + pp = ops->callbacks.gro_receive(head, skb); out_unlock: rcu_read_unlock(); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 0feede45bd28..b964f4250f35 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -148,14 +148,6 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb) !(IP6CB(skb)->flags & IP6SKB_REROUTED)); } -bool ip6_autoflowlabel(struct net *net, const struct ipv6_pinfo *np) -{ - if (!np->autoflowlabel_set) - return ip6_default_np_autolabel(net); - else - return np->autoflowlabel; -} - /* * xmit an sk_buff (used by TCP, SCTP and DCCP) * Note : socket lock is not held for SYNACK packets, but might be modified @@ -219,7 +211,7 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, hlimit = ip6_dst_hoplimit(dst); ip6_flow_hdr(hdr, tclass, ip6_make_flowlabel(net, skb, fl6->flowlabel, - ip6_autoflowlabel(net, np), fl6)); + np->autoflowlabel, fl6)); hdr->payload_len = htons(seg_len); hdr->nexthdr = proto; @@ -340,10 +332,6 @@ static int ip6_forward_proxy_check(struct sk_buff *skb) static inline int ip6_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { - struct dst_entry *dst = skb_dst(skb); - - IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); - IP6_ADD_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTOCTETS, skb->len); skb_sender_cpu_clear(skb); return dst_output(net, sk, skb); } @@ -538,6 +526,8 @@ int ip6_forward(struct sk_buff *skb) hdr->hop_limit--; + IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); + IP6_ADD_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTOCTETS, skb->len); return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, net, NULL, skb, skb->dev, dst->dev, ip6_forward_finish); @@ -559,8 +549,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->dev = from->dev; to->mark = from->mark; - skb_copy_hash(to, from); - #ifdef CONFIG_NET_SCHED to->tc_index = from->tc_index; #endif @@ -659,6 +647,8 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, *prevhdr = NEXTHDR_FRAGMENT; tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC); if (!tmp_hdr) { + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_FRAGFAILS); err = -ENOMEM; goto fail; } @@ -755,14 +745,13 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, * Fragment the datagram. */ + *prevhdr = NEXTHDR_FRAGMENT; troom = rt->dst.dev->needed_tailroom; /* * Keep copying data until we run out. */ while (left > 0) { - u8 *fragnexthdr_offset; - len = left; /* IF: it doesn't fit, use 'mtu' - the data space left */ if (len > mtu) @@ -777,6 +766,8 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, frag = alloc_skb(len + hlen + sizeof(struct frag_hdr) + hroom + troom, GFP_ATOMIC); if (!frag) { + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_FRAGFAILS); err = -ENOMEM; goto fail; } @@ -805,10 +796,6 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, */ skb_copy_from_linear_data(skb, skb_network_header(frag), hlen); - fragnexthdr_offset = skb_network_header(frag); - fragnexthdr_offset += prevhdr - skb_network_header(skb); - *fragnexthdr_offset = NEXTHDR_FRAGMENT; - /* * Build fragment header. */ @@ -1012,11 +999,6 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, } } #endif - if (ipv6_addr_v4mapped(&fl6->saddr) && - !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) { - err = -EAFNOSUPPORT; - goto out_err_release; - } return 0; @@ -1093,12 +1075,17 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, const struct in6_addr *final_dst) { struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); + int err; dst = ip6_sk_dst_check(sk, dst, fl6); - if (!dst) - dst = ip6_dst_lookup_flow(sk, fl6, final_dst); - return dst; + err = ip6_dst_lookup_tail(sock_net(sk), sk, &dst, fl6); + if (err) + return ERR_PTR(err); + if (final_dst) + fl6->daddr = *final_dst; + + return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); } EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); @@ -1213,11 +1200,11 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, if (WARN_ON(v6_cork->opt)) return -EINVAL; - v6_cork->opt = kzalloc(sizeof(*opt), sk->sk_allocation); + v6_cork->opt = kzalloc(opt->tot_len, sk->sk_allocation); if (unlikely(!v6_cork->opt)) return -ENOBUFS; - v6_cork->opt->tot_len = sizeof(*opt); + v6_cork->opt->tot_len = opt->tot_len; v6_cork->opt->opt_flen = opt->opt_flen; v6_cork->opt->opt_nflen = opt->opt_nflen; @@ -1280,7 +1267,7 @@ static int __ip6_append_data(struct sock *sk, unsigned int flags, int dontfrag) { struct sk_buff *skb, *skb_prev = NULL; - unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu; + unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu; int exthdrlen = 0; int dst_exthdrlen = 0; int hh_len; @@ -1316,12 +1303,6 @@ static int __ip6_append_data(struct sock *sk, sizeof(struct frag_hdr) : 0) + rt->rt6i_nfheader_len; - /* as per RFC 7112 section 5, the entire IPv6 Header Chain must fit - * the first fragment - */ - if (headersize + transhdrlen > mtu) - goto emsgsize; - if (cork->length + length > mtu - headersize && dontfrag && (sk->sk_protocol == IPPROTO_UDP || sk->sk_protocol == IPPROTO_RAW)) { @@ -1337,8 +1318,9 @@ static int __ip6_append_data(struct sock *sk, if (cork->length + length > maxnonfragsize - headersize) { emsgsize: - pmtu = max_t(int, mtu - headersize + sizeof(struct ipv6hdr), 0); - ipv6_local_error(sk, EMSGSIZE, fl6, pmtu); + ipv6_local_error(sk, EMSGSIZE, fl6, + mtu - headersize + + sizeof(struct ipv6hdr)); return -EMSGSIZE; } @@ -1377,8 +1359,8 @@ static int __ip6_append_data(struct sock *sk, cork->length += length; if ((skb && skb_is_gso(skb)) || - (((length + (skb ? skb->len : headersize)) > mtu) && - (skb_queue_len(queue) <= 1) && + (((length + fragheaderlen) > mtu) && + (skb_queue_len(&sk->sk_write_queue) <= 1) && (sk->sk_protocol == IPPROTO_UDP) && (rt->dst.dev->features & NETIF_F_UFO) && (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk))) { @@ -1531,8 +1513,7 @@ static int __ip6_append_data(struct sock *sk, if (copy > length) copy = length; - if (!(rt->dst.dev->features&NETIF_F_SG) && - skb_tailroom(skb) >= copy) { + if (!(rt->dst.dev->features&NETIF_F_SG)) { unsigned int off; off = skb->len; @@ -1695,7 +1676,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk, ip6_flow_hdr(hdr, v6_cork->tclass, ip6_make_flowlabel(net, skb, fl6->flowlabel, - ip6_autoflowlabel(net, np), fl6)); + np->autoflowlabel, fl6)); hdr->hop_limit = v6_cork->hop_limit; hdr->nexthdr = proto; hdr->saddr = fl6->saddr; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 3c2468bd0b7c..7f05bfde641f 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -122,6 +122,97 @@ static struct net_device_stats *ip6_get_stats(struct net_device *dev) return &dev->stats; } +/* + * Locking : hash tables are protected by RCU and RTNL + */ + +static void ip6_tnl_per_cpu_dst_set(struct ip6_tnl_dst *idst, + struct dst_entry *dst) +{ + write_seqlock_bh(&idst->lock); + dst_release(rcu_dereference_protected( + idst->dst, + lockdep_is_held(&idst->lock.lock))); + if (dst) { + dst_hold(dst); + idst->cookie = rt6_get_cookie((struct rt6_info *)dst); + } else { + idst->cookie = 0; + } + rcu_assign_pointer(idst->dst, dst); + write_sequnlock_bh(&idst->lock); +} + +struct dst_entry *ip6_tnl_dst_get(struct ip6_tnl *t) +{ + struct ip6_tnl_dst *idst; + struct dst_entry *dst; + unsigned int seq; + u32 cookie; + + idst = raw_cpu_ptr(t->dst_cache); + + rcu_read_lock(); + do { + seq = read_seqbegin(&idst->lock); + dst = rcu_dereference(idst->dst); + cookie = idst->cookie; + } while (read_seqretry(&idst->lock, seq)); + + if (dst && !atomic_inc_not_zero(&dst->__refcnt)) + dst = NULL; + rcu_read_unlock(); + + if (dst && dst->obsolete && !dst->ops->check(dst, cookie)) { + ip6_tnl_per_cpu_dst_set(idst, NULL); + dst_release(dst); + dst = NULL; + } + return dst; +} +EXPORT_SYMBOL_GPL(ip6_tnl_dst_get); + +void ip6_tnl_dst_reset(struct ip6_tnl *t) +{ + int i; + + for_each_possible_cpu(i) + ip6_tnl_per_cpu_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); +} +EXPORT_SYMBOL_GPL(ip6_tnl_dst_reset); + +void ip6_tnl_dst_set(struct ip6_tnl *t, struct dst_entry *dst) +{ + ip6_tnl_per_cpu_dst_set(raw_cpu_ptr(t->dst_cache), dst); + +} +EXPORT_SYMBOL_GPL(ip6_tnl_dst_set); + +void ip6_tnl_dst_destroy(struct ip6_tnl *t) +{ + if (!t->dst_cache) + return; + + ip6_tnl_dst_reset(t); + free_percpu(t->dst_cache); +} +EXPORT_SYMBOL_GPL(ip6_tnl_dst_destroy); + +int ip6_tnl_dst_init(struct ip6_tnl *t) +{ + int i; + + t->dst_cache = alloc_percpu(struct ip6_tnl_dst); + if (!t->dst_cache) + return -ENOMEM; + + for_each_possible_cpu(i) + seqlock_init(&per_cpu_ptr(t->dst_cache, i)->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(ip6_tnl_dst_init); + /** * ip6_tnl_lookup - fetch tunnel matching the end-point addresses * @remote: the address of the tunnel exit-point @@ -155,7 +246,6 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_ hash = HASH(&any, local); for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { if (ipv6_addr_equal(local, &t->parms.laddr) && - ipv6_addr_any(&t->parms.raddr) && (t->dev->flags & IFF_UP)) return t; } @@ -163,7 +253,6 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_ hash = HASH(remote, &any); for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { if (ipv6_addr_equal(remote, &t->parms.raddr) && - ipv6_addr_any(&t->parms.laddr) && (t->dev->flags & IFF_UP)) return t; } @@ -240,7 +329,7 @@ static void ip6_dev_free(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); - dst_cache_destroy(&t->dst_cache); + ip6_tnl_dst_destroy(t); free_percpu(dev->tstats); free_netdev(dev); } @@ -286,16 +375,13 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p) struct net_device *dev; struct ip6_tnl *t; char name[IFNAMSIZ]; - int err = -E2BIG; + int err = -ENOMEM; - if (p->name[0]) { - if (!dev_valid_name(p->name)) - goto failed; + if (p->name[0]) strlcpy(name, p->name, IFNAMSIZ); - } else { + else sprintf(name, "ip6tnl%%d"); - } - err = -ENOMEM; + dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, ip6_tnl_dev_setup); if (!dev) @@ -376,7 +462,7 @@ ip6_tnl_dev_uninit(struct net_device *dev) RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); else ip6_tnl_unlink(ip6n, t); - dst_cache_reset(&t->dst_cache); + ip6_tnl_dst_reset(t); dev_put(dev); } @@ -391,19 +477,18 @@ ip6_tnl_dev_uninit(struct net_device *dev) __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) { - const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw; - unsigned int nhoff = raw - skb->data; - unsigned int off = nhoff + sizeof(*ipv6h); - u8 next, nexthdr = ipv6h->nexthdr; + const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw; + __u8 nexthdr = ipv6h->nexthdr; + __u16 off = sizeof(*ipv6h); while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) { + __u16 optlen = 0; struct ipv6_opt_hdr *hdr; - u16 optlen; - - if (!pskb_may_pull(skb, off + sizeof(*hdr))) + if (raw + off + sizeof(*hdr) > skb->data && + !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr))) break; - hdr = (struct ipv6_opt_hdr *)(skb->data + off); + hdr = (struct ipv6_opt_hdr *) (raw + off); if (nexthdr == NEXTHDR_FRAGMENT) { struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr; if (frag_hdr->frag_off) @@ -414,29 +499,20 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) } else { optlen = ipv6_optlen(hdr); } - /* cache hdr->nexthdr, since pskb_may_pull() might - * invalidate hdr - */ - next = hdr->nexthdr; if (nexthdr == NEXTHDR_DEST) { - u16 i = 2; - - /* Remember : hdr is no longer valid at this point. */ - if (!pskb_may_pull(skb, off + optlen)) - break; - + __u16 i = off + 2; while (1) { struct ipv6_tlv_tnl_enc_lim *tel; /* No more room for encapsulation limit */ - if (i + sizeof(*tel) > optlen) + if (i + sizeof (*tel) > off + optlen) break; - tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data + off + i); + tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i]; /* return index of option if found and valid */ if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT && tel->length == 1) - return i + off - nhoff; + return i; /* else jump to next option */ if (tel->type) i += tel->length + 2; @@ -444,7 +520,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) i++; } } - nexthdr = next; + nexthdr = hdr->nexthdr; off += optlen; } return 0; @@ -961,7 +1037,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, struct ip6_tnl *t = netdev_priv(dev); struct net *net = t->net; struct net_device_stats *stats = &t->dev->stats; - struct ipv6hdr *ipv6h; + struct ipv6hdr *ipv6h = ipv6_hdr(skb); struct ipv6_tel_txoption opt; struct dst_entry *dst = NULL, *ndst = NULL; struct net_device *tdev; @@ -993,7 +1069,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr)); neigh_release(neigh); } else if (!fl6->flowi6_mark) - dst = dst_cache_get(&t->dst_cache); + dst = ip6_tnl_dst_get(t); if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr)) goto tx_err_link_failure; @@ -1057,7 +1133,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, } if (!fl6->flowi6_mark && ndst) - dst_cache_set_ip6(&t->dst_cache, ndst, &fl6->saddr); + ip6_tnl_dst_set(t, ndst); skb_dst_set(skb, dst); skb->transport_header = skb->network_header; @@ -1295,7 +1371,7 @@ ip6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p) t->parms.flowinfo = p->flowinfo; t->parms.link = p->link; t->parms.proto = p->proto; - dst_cache_reset(&t->dst_cache); + ip6_tnl_dst_reset(t); ip6_tnl_link_config(t); return 0; } @@ -1566,7 +1642,7 @@ ip6_tnl_dev_init_gen(struct net_device *dev) if (!dev->tstats) return -ENOMEM; - ret = dst_cache_init(&t->dst_cache, GFP_KERNEL); + ret = ip6_tnl_dst_init(t); if (ret) { free_percpu(dev->tstats); dev->tstats = NULL; diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 060862a6f2f2..24fb9c0efd00 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -189,12 +189,12 @@ static int vti6_tnl_create2(struct net_device *dev) struct vti6_net *ip6n = net_generic(net, vti6_net_id); int err; - dev->rtnl_link_ops = &vti6_link_ops; err = register_netdevice(dev); if (err < 0) goto out; strcpy(t->parms.name, dev->name); + dev->rtnl_link_ops = &vti6_link_ops; dev_hold(dev); vti6_tnl_link(ip6n, t); @@ -212,13 +212,10 @@ static struct ip6_tnl *vti6_tnl_create(struct net *net, struct __ip6_tnl_parm *p char name[IFNAMSIZ]; int err; - if (p->name[0]) { - if (!dev_valid_name(p->name)) - goto failed; + if (p->name[0]) strlcpy(name, p->name, IFNAMSIZ); - } else { + else sprintf(name, "ip6_vti%%d"); - } dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, vti6_dev_setup); if (!dev) @@ -437,7 +434,6 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) struct dst_entry *dst = skb_dst(skb); struct net_device *tdev; struct xfrm_state *x; - int pkt_len = skb->len; int err = -1; int mtu; @@ -469,34 +465,29 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) goto tx_err_dst_release; } + skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev))); + skb_dst_set(skb, dst); + skb->dev = skb_dst(skb)->dev; + mtu = dst_mtu(dst); if (!skb->ignore_df && skb->len > mtu) { skb_dst(skb)->ops->update_pmtu(dst, NULL, skb, mtu); - if (skb->protocol == htons(ETH_P_IPV6)) { - if (mtu < IPV6_MIN_MTU) - mtu = IPV6_MIN_MTU; - + if (skb->protocol == htons(ETH_P_IPV6)) icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); - } else { + else icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); - } - err = -EMSGSIZE; - goto tx_err_dst_release; + return -EMSGSIZE; } - skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev))); - skb_dst_set(skb, dst); - skb->dev = skb_dst(skb)->dev; - err = dst_output(t->net, skb->sk, skb); if (net_xmit_eval(err) == 0) { struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); u64_stats_update_begin(&tstats->syncp); - tstats->tx_bytes += pkt_len; + tstats->tx_bytes += skb->len; tstats->tx_packets++; u64_stats_update_end(&tstats->syncp); } else { @@ -650,7 +641,7 @@ vti6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p) t->parms.i_key = p->i_key; t->parms.o_key = p->o_key; t->parms.proto = p->proto; - dst_cache_reset(&t->dst_cache); + ip6_tnl_dst_reset(t); vti6_link_config(t); return 0; } @@ -690,10 +681,6 @@ vti6_parm_to_user(struct ip6_tnl_parm2 *u, const struct __ip6_tnl_parm *p) u->link = p->link; u->i_key = p->i_key; u->o_key = p->o_key; - if (u->i_key) - u->i_flags |= GRE_KEY; - if (u->o_key) - u->o_flags |= GRE_KEY; u->proto = p->proto; memcpy(u->name, p->name, sizeof(u->name)); diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 9b92960f024d..a10e77103c88 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -495,7 +495,6 @@ static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) return ERR_PTR(-ENOENT); it->mrt = mrt; - it->cache = NULL; return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1) : SEQ_START_TOKEN; } @@ -775,8 +774,7 @@ static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt) * Delete a VIF entry */ -static int mif6_delete(struct mr6_table *mrt, int vifi, int notify, - struct list_head *head) +static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head) { struct mif_device *v; struct net_device *dev; @@ -822,7 +820,7 @@ static int mif6_delete(struct mr6_table *mrt, int vifi, int notify, dev->ifindex, &in6_dev->cnf); } - if ((v->flags & MIFF_REGISTER) && !notify) + if (v->flags & MIFF_REGISTER) unregister_netdevice_queue(dev, head); dev_put(dev); @@ -1076,7 +1074,6 @@ static struct mfc6_cache *ip6mr_cache_alloc(void) struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); if (!c) return NULL; - c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1; c->mfc_un.res.minvif = MAXMIFS; return c; } @@ -1332,6 +1329,7 @@ static int ip6mr_device_event(struct notifier_block *this, struct mr6_table *mrt; struct mif_device *v; int ct; + LIST_HEAD(list); if (event != NETDEV_UNREGISTER) return NOTIFY_DONE; @@ -1340,9 +1338,10 @@ static int ip6mr_device_event(struct notifier_block *this, v = &mrt->vif6_table[0]; for (ct = 0; ct < mrt->maxvif; ct++, v++) { if (v->dev == dev) - mif6_delete(mrt, ct, 1, NULL); + mif6_delete(mrt, ct, &list); } } + unregister_netdevice_many(&list); return NOTIFY_DONE; } @@ -1551,7 +1550,7 @@ static void mroute_clean_tables(struct mr6_table *mrt, bool all) for (i = 0; i < mrt->maxvif; i++) { if (!all && (mrt->vif6_table[i].flags & VIFF_STATIC)) continue; - mif6_delete(mrt, i, 0, &list); + mif6_delete(mrt, i, &list); } unregister_netdevice_many(&list); @@ -1704,7 +1703,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns if (copy_from_user(&mifi, optval, sizeof(mifi_t))) return -EFAULT; rtnl_lock(); - ret = mif6_delete(mrt, mifi, 0, NULL); + ret = mif6_delete(mrt, mifi, NULL); rtnl_unlock(); return ret; @@ -1787,8 +1786,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns ret = 0; if (!ip6mr_new_table(net, v)) ret = -ENOMEM; - else - raw6_sk(sk)->ip6mr_table = v; + raw6_sk(sk)->ip6mr_table = v; rtnl_unlock(); return ret; } @@ -2277,8 +2275,8 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, return 1; } -int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm, - int nowait, u32 portid) +int ip6mr_get_route(struct net *net, + struct sk_buff *skb, struct rtmsg *rtm, int nowait) { int err; struct mr6_table *mrt; @@ -2323,7 +2321,6 @@ int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm, return -ENOMEM; } - NETLINK_CB(skb2).portid = portid; skb_reset_transport_header(skb2); skb_put(skb2, sizeof(struct ipv6hdr)); diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 50192b79ea26..81655af4c8e1 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -597,24 +597,16 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, if (val) { struct net_device *dev; - int midx; - rcu_read_lock(); + if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) + goto e_inval; - dev = dev_get_by_index_rcu(net, val); + dev = dev_get_by_index(net, val); if (!dev) { - rcu_read_unlock(); retv = -ENODEV; break; } - midx = l3mdev_master_ifindex_rcu(dev); - - rcu_read_unlock(); - - if (sk->sk_bound_dev_if && - sk->sk_bound_dev_if != val && - (!midx || midx != sk->sk_bound_dev_if)) - goto e_inval; + dev_put(dev); } np->mcast_oif = val; retv = 0; @@ -886,7 +878,6 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, break; case IPV6_AUTOFLOWLABEL: np->autoflowlabel = valbool; - np->autoflowlabel_set = 1; retv = 0; break; } @@ -919,8 +910,12 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, #ifdef CONFIG_NETFILTER /* we need to exclude all possible ENOPROTOOPTs except default case */ if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && - optname != IPV6_XFRM_POLICY) - err = nf_setsockopt(sk, PF_INET6, optname, optval, optlen); + optname != IPV6_XFRM_POLICY) { + lock_sock(sk); + err = nf_setsockopt(sk, PF_INET6, optname, optval, + optlen); + release_sock(sk); + } #endif return err; } @@ -950,9 +945,12 @@ int compat_ipv6_setsockopt(struct sock *sk, int level, int optname, #ifdef CONFIG_NETFILTER /* we need to exclude all possible ENOPROTOOPTs except default case */ if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && - optname != IPV6_XFRM_POLICY) - err = compat_nf_setsockopt(sk, PF_INET6, optname, optval, - optlen); + optname != IPV6_XFRM_POLICY) { + lock_sock(sk); + err = compat_nf_setsockopt(sk, PF_INET6, optname, + optval, optlen); + release_sock(sk); + } #endif return err; } @@ -1320,7 +1318,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, break; case IPV6_AUTOFLOWLABEL: - val = ip6_autoflowlabel(sock_net(sk), np); + val = np->autoflowlabel; break; default: @@ -1354,7 +1352,10 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, if (get_user(len, optlen)) return -EFAULT; - err = nf_getsockopt(sk, PF_INET6, optname, optval, &len); + lock_sock(sk); + err = nf_getsockopt(sk, PF_INET6, optname, optval, + &len); + release_sock(sk); if (err >= 0) err = put_user(len, optlen); } @@ -1393,7 +1394,10 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, if (get_user(len, optlen)) return -EFAULT; - err = compat_nf_getsockopt(sk, PF_INET6, optname, optval, &len); + lock_sock(sk); + err = compat_nf_getsockopt(sk, PF_INET6, + optname, optval, &len); + release_sock(sk); if (err >= 0) err = put_user(len, optlen); } diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 091cee551cd9..d64ee7e83664 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1668,16 +1668,16 @@ static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel) } static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, - int type, struct mld2_grec **ppgr, unsigned int mtu) + int type, struct mld2_grec **ppgr) { + struct net_device *dev = pmc->idev->dev; struct mld2_report *pmr; struct mld2_grec *pgr; - if (!skb) { - skb = mld_newpack(pmc->idev, mtu); - if (!skb) - return NULL; - } + if (!skb) + skb = mld_newpack(pmc->idev, dev->mtu); + if (!skb) + return NULL; pgr = (struct mld2_grec *)skb_put(skb, sizeof(struct mld2_grec)); pgr->grec_type = type; pgr->grec_auxwords = 0; @@ -1700,15 +1700,10 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, struct mld2_grec *pgr = NULL; struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list; int scount, stotal, first, isquery, truncate; - unsigned int mtu; if (pmc->mca_flags & MAF_NOREPORT) return skb; - mtu = READ_ONCE(dev->mtu); - if (mtu < IPV6_MIN_MTU) - return skb; - isquery = type == MLD2_MODE_IS_INCLUDE || type == MLD2_MODE_IS_EXCLUDE; truncate = type == MLD2_MODE_IS_EXCLUDE || @@ -1729,7 +1724,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { if (skb) mld_sendpack(skb); - skb = mld_newpack(idev, mtu); + skb = mld_newpack(idev, dev->mtu); } } first = 1; @@ -1756,12 +1751,12 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, pgr->grec_nsrcs = htons(scount); if (skb) mld_sendpack(skb); - skb = mld_newpack(idev, mtu); + skb = mld_newpack(idev, dev->mtu); first = 1; scount = 0; } if (first) { - skb = add_grhead(skb, pmc, type, &pgr, mtu); + skb = add_grhead(skb, pmc, type, &pgr); first = 0; } if (!skb) @@ -1795,7 +1790,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, mld_sendpack(skb); skb = NULL; /* add_grhead will get a new one */ } - skb = add_grhead(skb, pmc, type, &pgr, mtu); + skb = add_grhead(skb, pmc, type, &pgr); } } if (pgr) @@ -2061,8 +2056,7 @@ void ipv6_mc_dad_complete(struct inet6_dev *idev) mld_send_initial_cr(idev); idev->mc_dad_count--; if (idev->mc_dad_count) - mld_dad_start_timer(idev, - unsolicited_report_interval(idev)); + mld_dad_start_timer(idev, idev->mc_maxdelay); } } @@ -2074,8 +2068,7 @@ static void mld_dad_timer_expire(unsigned long data) if (idev->mc_dad_count) { idev->mc_dad_count--; if (idev->mc_dad_count) - mld_dad_start_timer(idev, - unsolicited_report_interval(idev)); + mld_dad_start_timer(idev, idev->mc_maxdelay); } in6_dev_put(idev); } @@ -2433,8 +2426,7 @@ static void mld_ifc_timer_expire(unsigned long data) if (idev->mc_ifc_count) { idev->mc_ifc_count--; if (idev->mc_ifc_count) - mld_ifc_start_timer(idev, - unsolicited_report_interval(idev)); + mld_ifc_start_timer(idev, idev->mc_maxdelay); } in6_dev_put(idev); } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index dfe55e7ef07d..3452f9037ad4 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1480,8 +1480,7 @@ static void ndisc_fill_redirect_hdr_option(struct sk_buff *skb, *(opt++) = (rd_len >> 3); opt += 6; - skb_copy_bits(orig_skb, skb_network_offset(orig_skb), opt, - rd_len - 8); + memcpy(opt, ipv6_hdr(orig_skb), rd_len - 8); } void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) @@ -1689,8 +1688,6 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, case NETDEV_CHANGEADDR: neigh_changeaddr(&nd_tbl, dev); fib6_run_gc(0, net, false); - /* fallthrough */ - case NETDEV_UP: idev = in6_dev_get(dev); if (!idev) break; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index bc36aae12597..45c3a9e04486 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -464,8 +464,7 @@ ip6t_do_table(struct sk_buff *skb, there are loops. Puts hook bitmask in comefrom. */ static int mark_source_chains(const struct xt_table_info *newinfo, - unsigned int valid_hooks, void *entry0, - unsigned int *offsets) + unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -538,8 +537,6 @@ mark_source_chains(const struct xt_table_info *newinfo, size = e->next_offset; e = (struct ip6t_entry *) (entry0 + pos + size); - if (pos + size >= newinfo->size) - return 0; e->counters.pcnt = pos; pos += size; } else { @@ -558,16 +555,9 @@ mark_source_chains(const struct xt_table_info *newinfo, /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); - if (!xt_find_jump_offset(offsets, newpos, - newinfo->number)) - return 0; - e = (struct ip6t_entry *) - (entry0 + newpos); } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; - if (newpos >= newinfo->size) - return 0; } e = (struct ip6t_entry *) (entry0 + newpos); @@ -594,6 +584,27 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) module_put(par.match->me); } +static int +check_entry(const struct ip6t_entry *e, const char *name) +{ + const struct xt_entry_target *t; + + if (!ip6_checkentry(&e->ipv6)) { + duprintf("ip_tables: ip check failed %p %s.\n", e, name); + return -EINVAL; + } + + if (e->target_offset + sizeof(struct xt_entry_target) > + e->next_offset) + return -EINVAL; + + t = ip6t_get_target_c(e); + if (e->target_offset + t->u.target_size > e->next_offset) + return -EINVAL; + + return 0; +} + static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) { const struct ip6t_ip6 *ipv6 = par->entryinfo; @@ -663,8 +674,7 @@ static int check_target(struct ip6t_entry *e, struct net *net, const char *name) static int find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, - unsigned int size, - struct xt_percpu_counter_alloc_state *alloc_state) + unsigned int size) { struct xt_entry_target *t; struct xt_target *target; @@ -673,11 +683,15 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, struct xt_mtchk_param mtpar; struct xt_entry_match *ematch; - if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) + ret = check_entry(e, name); + if (ret) + return ret; + + e->counters.pcnt = xt_percpu_counter_alloc(); + if (IS_ERR_VALUE(e->counters.pcnt)) return -ENOMEM; j = 0; - memset(&mtpar, 0, sizeof(mtpar)); mtpar.net = net; mtpar.table = name; mtpar.entryinfo = &e->ipv6; @@ -713,7 +727,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, cleanup_match(ematch, net); } - xt_percpu_counter_free(&e->counters); + xt_percpu_counter_free(e->counters.pcnt); return ret; } @@ -743,11 +757,9 @@ check_entry_size_and_hooks(struct ip6t_entry *e, unsigned int valid_hooks) { unsigned int h; - int err; if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 || - (unsigned char *)e + sizeof(struct ip6t_entry) >= limit || - (unsigned char *)e + e->next_offset > limit) { + (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) { duprintf("Bad offset %p\n", e); return -EINVAL; } @@ -759,14 +771,6 @@ check_entry_size_and_hooks(struct ip6t_entry *e, return -EINVAL; } - if (!ip6_checkentry(&e->ipv6)) - return -EINVAL; - - err = xt_check_entry_offsets(e, e->elems, e->target_offset, - e->next_offset); - if (err) - return err; - /* Check hooks & underflows */ for (h = 0; h < NF_INET_NUMHOOKS; h++) { if (!(valid_hooks & (1 << h))) @@ -808,7 +812,8 @@ static void cleanup_entry(struct ip6t_entry *e, struct net *net) if (par.target->destroy != NULL) par.target->destroy(&par); module_put(par.target->me); - xt_percpu_counter_free(&e->counters); + + xt_percpu_counter_free(e->counters.pcnt); } /* Checks and translates the user-supplied table segment (held in @@ -817,9 +822,7 @@ static int translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, const struct ip6t_replace *repl) { - struct xt_percpu_counter_alloc_state alloc_state = { 0 }; struct ip6t_entry *iter; - unsigned int *offsets; unsigned int i; int ret = 0; @@ -833,9 +836,6 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, } duprintf("translate_table: size %u\n", newinfo->size); - offsets = xt_alloc_entry_offsets(newinfo->number); - if (!offsets) - return -ENOMEM; i = 0; /* Walk through entries, checking offsets. */ @@ -845,10 +845,9 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, repl->hook_entry, repl->underflow, repl->valid_hooks); - if (ret != 0) - goto out_free; - if (i < repl->num_entries) - offsets[i] = (void *)iter - entry0; + if (ret != 0) { + return ret; + } ++i; if (strcmp(ip6t_get_target(iter)->u.user.name, XT_ERROR_TARGET) == 0) { @@ -856,11 +855,10 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, } } - ret = -EINVAL; if (i != repl->num_entries) { duprintf("translate_table: %u not %u entries\n", i, repl->num_entries); - goto out_free; + return -EINVAL; } /* Check hooks all assigned */ @@ -871,26 +869,22 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, if (newinfo->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", i, repl->hook_entry[i]); - goto out_free; + return -EINVAL; } if (newinfo->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", i, repl->underflow[i]); - goto out_free; + return -EINVAL; } } - if (!mark_source_chains(newinfo, repl->valid_hooks, entry0, offsets)) { - ret = -ELOOP; - goto out_free; - } - kvfree(offsets); + if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) + return -ELOOP; /* Finally, each sanity check must pass */ i = 0; xt_entry_foreach(iter, entry0, newinfo->size) { - ret = find_check_entry(iter, net, repl->name, repl->size, - &alloc_state); + ret = find_check_entry(iter, net, repl->name, repl->size); if (ret != 0) break; ++i; @@ -905,9 +899,6 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, return ret; } - return ret; - out_free: - kvfree(offsets); return ret; } @@ -1338,16 +1329,55 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, unsigned int i; struct xt_counters_info tmp; struct xt_counters *paddc; + unsigned int num_counters; + char *name; + int size; + void *ptmp; struct xt_table *t; const struct xt_table_info *private; int ret = 0; struct ip6t_entry *iter; unsigned int addend; +#ifdef CONFIG_COMPAT + struct compat_xt_counters_info compat_tmp; + + if (compat) { + ptmp = &compat_tmp; + size = sizeof(struct compat_xt_counters_info); + } else +#endif + { + ptmp = &tmp; + size = sizeof(struct xt_counters_info); + } - paddc = xt_copy_counters_from_user(user, len, &tmp, compat); - if (IS_ERR(paddc)) - return PTR_ERR(paddc); - t = xt_find_table_lock(net, AF_INET6, tmp.name); + if (copy_from_user(ptmp, user, size) != 0) + return -EFAULT; + +#ifdef CONFIG_COMPAT + if (compat) { + num_counters = compat_tmp.num_counters; + name = compat_tmp.name; + } else +#endif + { + num_counters = tmp.num_counters; + name = tmp.name; + } + + if (len != size + num_counters * sizeof(struct xt_counters)) + return -EINVAL; + + paddc = vmalloc(len - size); + if (!paddc) + return -ENOMEM; + + if (copy_from_user(paddc, user + size, len - size) != 0) { + ret = -EFAULT; + goto free; + } + + t = xt_find_table_lock(net, AF_INET6, name); if (IS_ERR_OR_NULL(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; @@ -1355,7 +1385,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, local_bh_disable(); private = t->private; - if (private->number != tmp.num_counters) { + if (private->number != num_counters) { ret = -EINVAL; goto unlock_up_free; } @@ -1434,6 +1464,7 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, static int compat_find_calc_match(struct xt_entry_match *m, + const char *name, const struct ip6t_ip6 *ipv6, int *size) { @@ -1468,19 +1499,21 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, struct xt_table_info *newinfo, unsigned int *size, const unsigned char *base, - const unsigned char *limit) + const unsigned char *limit, + const unsigned int *hook_entries, + const unsigned int *underflows, + const char *name) { struct xt_entry_match *ematch; struct xt_entry_target *t; struct xt_target *target; unsigned int entry_offset; unsigned int j; - int ret, off; + int ret, off, h; duprintf("check_compat_entry_size_and_hooks %p\n", e); if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 || - (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit || - (unsigned char *)e + e->next_offset > limit) { + (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit) { duprintf("Bad offset %p, limit = %p\n", e, limit); return -EINVAL; } @@ -1492,11 +1525,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, return -EINVAL; } - if (!ip6_checkentry(&e->ipv6)) - return -EINVAL; - - ret = xt_compat_check_entry_offsets(e, e->elems, - e->target_offset, e->next_offset); + /* For purposes of check_entry casting the compat entry is fine */ + ret = check_entry((struct ip6t_entry *)e, name); if (ret) return ret; @@ -1504,7 +1534,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, entry_offset = (void *)e - (void *)base; j = 0; xt_ematch_foreach(ematch, e) { - ret = compat_find_calc_match(ematch, &e->ipv6, &off); + ret = compat_find_calc_match(ematch, name, &e->ipv6, &off); if (ret != 0) goto release_matches; ++j; @@ -1527,6 +1557,17 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, if (ret) goto out; + /* Check hooks & underflows */ + for (h = 0; h < NF_INET_NUMHOOKS; h++) { + if ((unsigned char *)e - base == hook_entries[h]) + newinfo->hook_entry[h] = hook_entries[h]; + if ((unsigned char *)e - base == underflows[h]) + newinfo->underflow[h] = underflows[h]; + } + + /* Clear counters and comefrom */ + memset(&e->counters, 0, sizeof(e->counters)); + e->comefrom = 0; return 0; out: @@ -1540,17 +1581,18 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, return ret; } -static void +static int compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, - unsigned int *size, + unsigned int *size, const char *name, struct xt_table_info *newinfo, unsigned char *base) { struct xt_entry_target *t; struct ip6t_entry *de; unsigned int origsize; - int h; + int ret, h; struct xt_entry_match *ematch; + ret = 0; origsize = *size; de = (struct ip6t_entry *)*dstptr; memcpy(de, e, sizeof(struct ip6t_entry)); @@ -1559,9 +1601,11 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, *dstptr += sizeof(struct ip6t_entry); *size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); - xt_ematch_foreach(ematch, e) - xt_compat_match_from_user(ematch, dstptr, size); - + xt_ematch_foreach(ematch, e) { + ret = xt_compat_match_from_user(ematch, dstptr, size); + if (ret != 0) + return ret; + } de->target_offset = e->target_offset - (origsize - *size); t = compat_ip6t_get_target(e); xt_compat_target_from_user(t, dstptr, size); @@ -1573,82 +1617,182 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, if ((unsigned char *)de - base < newinfo->underflow[h]) newinfo->underflow[h] -= origsize - *size; } + return ret; +} + +static int compat_check_entry(struct ip6t_entry *e, struct net *net, + const char *name) +{ + unsigned int j; + int ret = 0; + struct xt_mtchk_param mtpar; + struct xt_entry_match *ematch; + + e->counters.pcnt = xt_percpu_counter_alloc(); + if (IS_ERR_VALUE(e->counters.pcnt)) + return -ENOMEM; + j = 0; + mtpar.net = net; + mtpar.table = name; + mtpar.entryinfo = &e->ipv6; + mtpar.hook_mask = e->comefrom; + mtpar.family = NFPROTO_IPV6; + xt_ematch_foreach(ematch, e) { + ret = check_match(ematch, &mtpar); + if (ret != 0) + goto cleanup_matches; + ++j; + } + + ret = check_target(e, net, name); + if (ret) + goto cleanup_matches; + return 0; + + cleanup_matches: + xt_ematch_foreach(ematch, e) { + if (j-- == 0) + break; + cleanup_match(ematch, net); + } + + xt_percpu_counter_free(e->counters.pcnt); + + return ret; } static int translate_compat_table(struct net *net, + const char *name, + unsigned int valid_hooks, struct xt_table_info **pinfo, void **pentry0, - const struct compat_ip6t_replace *compatr) + unsigned int total_size, + unsigned int number, + unsigned int *hook_entries, + unsigned int *underflows) { unsigned int i, j; struct xt_table_info *newinfo, *info; void *pos, *entry0, *entry1; struct compat_ip6t_entry *iter0; - struct ip6t_replace repl; + struct ip6t_entry *iter1; unsigned int size; int ret = 0; info = *pinfo; entry0 = *pentry0; - size = compatr->size; - info->number = compatr->num_entries; + size = total_size; + info->number = number; + + /* Init all hooks to impossible value. */ + for (i = 0; i < NF_INET_NUMHOOKS; i++) { + info->hook_entry[i] = 0xFFFFFFFF; + info->underflow[i] = 0xFFFFFFFF; + } duprintf("translate_compat_table: size %u\n", info->size); j = 0; xt_compat_lock(AF_INET6); - xt_compat_init_offsets(AF_INET6, compatr->num_entries); + xt_compat_init_offsets(AF_INET6, number); /* Walk through entries, checking offsets. */ - xt_entry_foreach(iter0, entry0, compatr->size) { + xt_entry_foreach(iter0, entry0, total_size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, - entry0 + compatr->size); + entry0 + total_size, + hook_entries, + underflows, + name); if (ret != 0) goto out_unlock; ++j; } ret = -EINVAL; - if (j != compatr->num_entries) { + if (j != number) { duprintf("translate_compat_table: %u not %u entries\n", - j, compatr->num_entries); + j, number); goto out_unlock; } + /* Check hooks all assigned */ + for (i = 0; i < NF_INET_NUMHOOKS; i++) { + /* Only hooks which are valid */ + if (!(valid_hooks & (1 << i))) + continue; + if (info->hook_entry[i] == 0xFFFFFFFF) { + duprintf("Invalid hook entry %u %u\n", + i, hook_entries[i]); + goto out_unlock; + } + if (info->underflow[i] == 0xFFFFFFFF) { + duprintf("Invalid underflow %u %u\n", + i, underflows[i]); + goto out_unlock; + } + } + ret = -ENOMEM; newinfo = xt_alloc_table_info(size); if (!newinfo) goto out_unlock; - newinfo->number = compatr->num_entries; + newinfo->number = number; for (i = 0; i < NF_INET_NUMHOOKS; i++) { - newinfo->hook_entry[i] = compatr->hook_entry[i]; - newinfo->underflow[i] = compatr->underflow[i]; + newinfo->hook_entry[i] = info->hook_entry[i]; + newinfo->underflow[i] = info->underflow[i]; } entry1 = newinfo->entries; pos = entry1; - size = compatr->size; - xt_entry_foreach(iter0, entry0, compatr->size) - compat_copy_entry_from_user(iter0, &pos, &size, - newinfo, entry1); - - /* all module references in entry0 are now gone. */ + size = total_size; + xt_entry_foreach(iter0, entry0, total_size) { + ret = compat_copy_entry_from_user(iter0, &pos, &size, + name, newinfo, entry1); + if (ret != 0) + break; + } xt_compat_flush_offsets(AF_INET6); xt_compat_unlock(AF_INET6); + if (ret) + goto free_newinfo; - memcpy(&repl, compatr, sizeof(*compatr)); + ret = -ELOOP; + if (!mark_source_chains(newinfo, valid_hooks, entry1)) + goto free_newinfo; - for (i = 0; i < NF_INET_NUMHOOKS; i++) { - repl.hook_entry[i] = newinfo->hook_entry[i]; - repl.underflow[i] = newinfo->underflow[i]; + i = 0; + xt_entry_foreach(iter1, entry1, newinfo->size) { + ret = compat_check_entry(iter1, net, name); + if (ret != 0) + break; + ++i; + if (strcmp(ip6t_get_target(iter1)->u.user.name, + XT_ERROR_TARGET) == 0) + ++newinfo->stacksize; + } + if (ret) { + /* + * The first i matches need cleanup_entry (calls ->destroy) + * because they had called ->check already. The other j-i + * entries need only release. + */ + int skip = i; + j -= i; + xt_entry_foreach(iter0, entry0, newinfo->size) { + if (skip-- > 0) + continue; + if (j-- == 0) + break; + compat_release_entry(iter0); + } + xt_entry_foreach(iter1, entry1, newinfo->size) { + if (i-- == 0) + break; + cleanup_entry(iter1, net); + } + xt_free_table_info(newinfo); + return ret; } - - repl.num_counters = 0; - repl.counters = NULL; - repl.size = newinfo->size; - ret = translate_table(net, newinfo, entry1, &repl); - if (ret) - goto free_newinfo; *pinfo = newinfo; *pentry0 = entry1; @@ -1657,16 +1801,17 @@ translate_compat_table(struct net *net, free_newinfo: xt_free_table_info(newinfo); - return ret; -out_unlock: - xt_compat_flush_offsets(AF_INET6); - xt_compat_unlock(AF_INET6); - xt_entry_foreach(iter0, entry0, compatr->size) { +out: + xt_entry_foreach(iter0, entry0, total_size) { if (j-- == 0) break; compat_release_entry(iter0); } return ret; +out_unlock: + xt_compat_flush_offsets(AF_INET6); + xt_compat_unlock(AF_INET6); + goto out; } static int @@ -1702,7 +1847,10 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) goto free_newinfo; } - ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp); + ret = translate_compat_table(net, tmp.name, tmp.valid_hooks, + &newinfo, &loc_cpu_entry, tmp.size, + tmp.num_entries, tmp.hook_entry, + tmp.underflow); if (ret != 0) goto free_newinfo; @@ -2077,7 +2225,6 @@ static struct xt_match ip6t_builtin_mt[] __read_mostly = { .checkentry = icmp6_checkentry, .proto = IPPROTO_ICMPV6, .family = NFPROTO_IPV6, - .me = THIS_MODULE, }, }; diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index aa051d9d4a96..1aa5848764a7 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -226,27 +226,20 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { static int ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len) { - struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 }; - const struct ipv6_pinfo *inet6 = inet6_sk(sk); const struct inet_sock *inet = inet_sk(sk); + const struct ipv6_pinfo *inet6 = inet6_sk(sk); const struct nf_conntrack_tuple_hash *h; struct sockaddr_in6 sin6; + struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 }; struct nf_conn *ct; - __be32 flow_label; - int bound_dev_if; - lock_sock(sk); tuple.src.u3.in6 = sk->sk_v6_rcv_saddr; tuple.src.u.tcp.port = inet->inet_sport; tuple.dst.u3.in6 = sk->sk_v6_daddr; tuple.dst.u.tcp.port = inet->inet_dport; tuple.dst.protonum = sk->sk_protocol; - bound_dev_if = sk->sk_bound_dev_if; - flow_label = inet6->flow_label; - release_sock(sk); - if (tuple.dst.protonum != IPPROTO_TCP && - tuple.dst.protonum != IPPROTO_SCTP) + if (sk->sk_protocol != IPPROTO_TCP && sk->sk_protocol != IPPROTO_SCTP) return -ENOPROTOOPT; if (*len < 0 || (unsigned int) *len < sizeof(sin6)) @@ -264,13 +257,14 @@ ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len) sin6.sin6_family = AF_INET6; sin6.sin6_port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port; - sin6.sin6_flowinfo = flow_label & IPV6_FLOWINFO_MASK; + sin6.sin6_flowinfo = inet6->flow_label & IPV6_FLOWINFO_MASK; memcpy(&sin6.sin6_addr, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6, sizeof(sin6.sin6_addr)); nf_ct_put(ct); - sin6.sin6_scope_id = ipv6_iface_scope_id(&sin6.sin6_addr, bound_dev_if); + sin6.sin6_scope_id = ipv6_iface_scope_id(&sin6.sin6_addr, + sk->sk_bound_dev_if); return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0; } diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 838b65a59a73..bab4441ed4e4 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -118,7 +118,7 @@ static int nf_ct_frag6_sysctl_register(struct net *net) if (hdr == NULL) goto err_reg; - net->nf_frag_frags_hdr = hdr; + net->nf_frag.sysctl.frags_hdr = hdr; return 0; err_reg: @@ -132,8 +132,8 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net) { struct ctl_table *table; - table = net->nf_frag_frags_hdr->ctl_table_arg; - unregister_net_sysctl_table(net->nf_frag_frags_hdr); + table = net->nf_frag.sysctl.frags_hdr->ctl_table_arg; + unregister_net_sysctl_table(net->nf_frag.sysctl.frags_hdr); if (!net_eq(net, &init_net)) kfree(table); } @@ -649,12 +649,18 @@ EXPORT_SYMBOL_GPL(nf_ct_frag6_consume_orig); static int nf_ct_net_init(struct net *net) { + int res; + net->nf_frag.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; net->nf_frag.frags.low_thresh = IPV6_FRAG_LOW_THRESH; net->nf_frag.frags.timeout = IPV6_FRAG_TIMEOUT; - inet_frags_init_net(&net->nf_frag.frags); - - return nf_ct_frag6_sysctl_register(net); + res = inet_frags_init_net(&net->nf_frag.frags); + if (res) + return res; + res = nf_ct_frag6_sysctl_register(net); + if (res) + inet_frags_uninit_net(&net->nf_frag.frags); + return res; } static void nf_ct_net_exit(struct net *net) diff --git a/net/ipv6/netfilter/nf_dup_ipv6.c b/net/ipv6/netfilter/nf_dup_ipv6.c index 4a84b5ad9ecb..6989c70ae29f 100644 --- a/net/ipv6/netfilter/nf_dup_ipv6.c +++ b/net/ipv6/netfilter/nf_dup_ipv6.c @@ -33,7 +33,6 @@ static bool nf_dup_ipv6_route(struct net *net, struct sk_buff *skb, fl6.daddr = *gw; fl6.flowlabel = (__force __be32)(((iph->flow_lbl[0] & 0xF) << 16) | (iph->flow_lbl[1] << 8) | iph->flow_lbl[2]); - fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH; dst = ip6_route_output(net, NULL, &fl6); if (dst->error) { dst_release(dst); diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c index 7b9c2cabd495..238e70c3f7b7 100644 --- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c @@ -99,10 +99,6 @@ static bool nf_nat_ipv6_manip_pkt(struct sk_buff *skb, !l4proto->manip_pkt(skb, &nf_nat_l3proto_ipv6, iphdroff, hdroff, target, maniptype)) return false; - - /* must reload, offset might have changed */ - ipv6h = (void *)skb->data + iphdroff; - manip_addr: if (maniptype == NF_NAT_MANIP_SRC) ipv6h->saddr = target->src.u3.in6; diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c index 7117e5bef412..e0f922b777e3 100644 --- a/net/ipv6/netfilter/nf_reject_ipv6.c +++ b/net/ipv6/netfilter/nf_reject_ipv6.c @@ -157,7 +157,6 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) fl6.daddr = oip6h->saddr; fl6.fl6_sport = otcph->dest; fl6.fl6_dport = otcph->source; - fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark); security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); dst = ip6_route_output(net, NULL, &fl6); if (dst == NULL || dst->error) { @@ -181,8 +180,6 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) skb_dst_set(nskb, dst); - nskb->mark = fl6.flowi6_mark; - skb_reserve(nskb, hh_len + dst->header_len); ip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP, ip6_dst_hoplimit(dst)); diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index f99a04674419..291c21fd96e9 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c @@ -86,6 +86,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) while (offset <= packet_len) { struct ipv6_opt_hdr *exthdr; + unsigned int len; switch (**nexthdr) { @@ -111,9 +112,10 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + offset); - offset += ipv6_optlen(exthdr); - if (offset > IPV6_MAXPLEN) + len = ipv6_optlen(exthdr); + if (len + offset >= IPV6_MAXPLEN) return -EINVAL; + offset += len; *nexthdr = &exthdr->nexthdr; } @@ -152,8 +154,6 @@ int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb) ipv6_hdr(skb)->payload_len = htons(len); IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); - skb->protocol = htons(ETH_P_IPV6); - return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, NULL, skb_dst(skb)->dev, dst_output); diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index c65c191d31c9..e970aceb5f29 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -50,7 +50,7 @@ static struct inet_protosw pingv6_protosw = { .type = SOCK_DGRAM, .protocol = IPPROTO_ICMPV6, .prot = &pingv6_prot, - .ops = &inet6_sockraw_ops, + .ops = &inet6_dgram_ops, .flags = INET_PROTOSW_REUSE, }; @@ -151,10 +151,8 @@ int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) rt = (struct rt6_info *) dst; np = inet6_sk(sk); - if (!np) { - err = -EBADF; - goto dst_err_out; - } + if (!np) + return -EBADF; if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) fl6.flowi6_oif = np->mcast_oif; @@ -189,9 +187,6 @@ int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) } release_sock(sk); -dst_err_out: - dst_release(dst); - if (err) return err; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 0ef8e114c8ab..4db4ad2e391d 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -589,11 +589,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, } offset += skb_transport_offset(skb); - err = skb_copy_bits(skb, offset, &csum, 2); - if (err < 0) { - ip6_flush_pending_frames(sk); - goto out; - } + BUG_ON(skb_copy_bits(skb, offset, &csum, 2)); /* in case cksum was not initialized */ if (unlikely(csum)) @@ -1147,7 +1143,8 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) spin_lock_bh(&sk->sk_receive_queue.lock); skb = skb_peek(&sk->sk_receive_queue); if (skb) - amount = skb->len; + amount = skb_tail_pointer(skb) - + skb_transport_header(skb); spin_unlock_bh(&sk->sk_receive_queue.lock); return put_user(amount, (int __user *)arg); } @@ -1304,7 +1301,7 @@ void raw6_proc_exit(void) #endif /* CONFIG_PROC_FS */ /* Same as inet6_dgram_ops, sans udp_poll. */ -const struct proto_ops inet6_sockraw_ops = { +static const struct proto_ops inet6_sockraw_ops = { .family = PF_INET6, .owner = THIS_MODULE, .release = inet6_release, diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 58f2139ebb5e..a234552a7e3d 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -708,13 +708,19 @@ static void ip6_frags_sysctl_unregister(void) static int __net_init ipv6_frags_init_net(struct net *net) { + int res; + net->ipv6.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; net->ipv6.frags.low_thresh = IPV6_FRAG_LOW_THRESH; net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT; - inet_frags_init_net(&net->ipv6.frags); - - return ip6_frags_ns_sysctl_register(net); + res = inet_frags_init_net(&net->ipv6.frags); + if (res) + return res; + res = ip6_frags_ns_sysctl_register(net); + if (res) + inet_frags_uninit_net(&net->ipv6.frags); + return res; } static void __net_exit ipv6_frags_exit_net(struct net *net) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 0a7403b9d572..b1db865b1c79 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -847,9 +847,6 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net, struct fib6_node *fn; struct rt6_info *rt; - if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF) - flags &= ~RT6_LOOKUP_F_IFACE; - read_lock_bh(&table->tb6_lock); fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); restart: @@ -1247,9 +1244,7 @@ static void rt6_dst_from_metrics_check(struct rt6_info *rt) static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie) { - u32 rt_cookie; - - if (!rt6_get_cookie_safe(rt, &rt_cookie) || rt_cookie != cookie) + if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie)) return NULL; if (rt6_check_expired(rt)) @@ -1317,14 +1312,8 @@ static void ip6_link_failure(struct sk_buff *skb) if (rt->rt6i_flags & RTF_CACHE) { dst_hold(&rt->dst); ip6_del_rt(rt); - } else { - struct fib6_node *fn; - - rcu_read_lock(); - fn = rcu_dereference(rt->rt6i_node); - if (fn && (rt->rt6i_flags & RTF_DEFAULT)) - fn->fn_sernum = -1; - rcu_read_unlock(); + } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) { + rt->rt6i_node->fn_sernum = -1; } } } @@ -1341,8 +1330,7 @@ static void rt6_do_update_pmtu(struct rt6_info *rt, u32 mtu) static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt) { return !(rt->rt6i_flags & RTF_CACHE) && - (rt->rt6i_flags & RTF_PCPU || - rcu_access_pointer(rt->rt6i_node)); + (rt->rt6i_flags & RTF_PCPU || rt->rt6i_node); } static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, @@ -1618,7 +1606,6 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, } rt->dst.flags |= DST_HOST; - rt->dst.input = ip6_input; rt->dst.output = ip6_output; atomic_set(&rt->dst.__refcnt, 1); rt->rt6i_gateway = fl6->daddr; @@ -1772,10 +1759,6 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg) int addr_type; int err = -EINVAL; - /* RTF_PCPU is an internal flag; can not be set by userspace */ - if (cfg->fc_flags & RTF_PCPU) - goto out; - if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128) goto out; #ifndef CONFIG_IPV6_SUBTREES @@ -2102,8 +2085,6 @@ static int ip6_route_del(struct fib6_config *cfg) continue; if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric) continue; - if (cfg->fc_protocol && cfg->fc_protocol != rt->rt6i_protocol) - continue; dst_hold(&rt->dst); read_unlock_bh(&table->tb6_lock); @@ -2702,7 +2683,6 @@ void rt6_mtu_change(struct net_device *dev, unsigned int mtu) static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { [RTA_GATEWAY] = { .len = sizeof(struct in6_addr) }, - [RTA_PREFSRC] = { .len = sizeof(struct in6_addr) }, [RTA_OIF] = { .type = NLA_U32 }, [RTA_IIF] = { .type = NLA_U32 }, [RTA_PRIORITY] = { .type = NLA_U32 }, @@ -2712,7 +2692,6 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { [RTA_ENCAP_TYPE] = { .type = NLA_U16 }, [RTA_ENCAP] = { .type = NLA_NESTED }, [RTA_UID] = { .type = NLA_U32 }, - [RTA_TABLE] = { .type = NLA_U32 }, }; static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, @@ -2840,11 +2819,17 @@ static int ip6_route_info_append(struct list_head *rt6_nh_list, struct rt6_info *rt, struct fib6_config *r_cfg) { struct rt6_nh *nh; + struct rt6_info *rtnh; int err = -EEXIST; list_for_each_entry(nh, rt6_nh_list, next) { /* check if rt6_info already exists */ - if (rt6_duplicate_nexthop(nh->rt6_info, rt)) + rtnh = nh->rt6_info; + + if (rtnh->dst.dev == rt->dst.dev && + rtnh->rt6i_idev == rt->rt6i_idev && + ipv6_addr_equal(&rtnh->rt6i_gateway, + &rt->rt6i_gateway)) return err; } @@ -3147,9 +3132,7 @@ static int rt6_fill_node(struct net *net, if (iif) { #ifdef CONFIG_IPV6_MROUTE if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) { - int err = ip6mr_get_route(net, skb, rtm, nowait, - portid); - + int err = ip6mr_get_route(net, skb, rtm, nowait); if (err <= 0) { if (!nowait) { if (err == 0) @@ -3203,8 +3186,7 @@ static int rt6_fill_node(struct net *net, if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->rt6i_flags))) goto nla_put_failure; - if (lwtunnel_fill_encap(skb, rt->dst.lwtstate) < 0) - goto nla_put_failure; + lwtunnel_fill_encap(skb, rt->dst.lwtstate); nlmsg_end(skb, nlh); return 0; @@ -3370,10 +3352,7 @@ static int ip6_route_dev_notify(struct notifier_block *this, struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); - if (!(dev->flags & IFF_LOOPBACK)) - return NOTIFY_OK; - - if (event == NETDEV_REGISTER) { + if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { net->ipv6.ip6_null_entry->dst.dev = dev; net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -3381,16 +3360,6 @@ static int ip6_route_dev_notify(struct notifier_block *this, net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); -#endif - } else if (event == NETDEV_UNREGISTER && - dev->reg_state != NETREG_UNREGISTERED) { - /* NETDEV_UNREGISTER could be fired for multiple times by - * netdev_wait_allrefs(). Make sure we only call this once. - */ - in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev); -#ifdef CONFIG_IPV6_MULTIPLE_TABLES - in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev); - in6_dev_put(net->ipv6.ip6_blk_hole_entry->rt6i_idev); #endif } @@ -3698,24 +3667,9 @@ static struct pernet_operations ip6_route_net_late_ops = { static struct notifier_block ip6_route_dev_notifier = { .notifier_call = ip6_route_dev_notify, - .priority = ADDRCONF_NOTIFY_PRIORITY - 10, + .priority = 0, }; -void __init ip6_route_init_special_entries(void) -{ - /* Registering of the loopback is done before this portion of code, - * the loopback reference in rt6_info will not be taken, do it - * manually for init_net */ - init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev; - init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); - #ifdef CONFIG_IPV6_MULTIPLE_TABLES - init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev; - init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); - init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; - init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); - #endif -} - int __init ip6_route_init(void) { int ret; @@ -3742,6 +3696,17 @@ int __init ip6_route_init(void) ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; + /* Registering of the loopback is done before this portion of code, + * the loopback reference in rt6_info will not be taken, do it + * manually for init_net */ + init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev; + init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev; + init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); + init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; + init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); + #endif ret = fib6_init(); if (ret) goto out_register_subsys; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 11282ffca567..dcccae86190f 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -176,7 +176,7 @@ static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) #ifdef CONFIG_IPV6_SIT_6RD struct ip_tunnel *t = netdev_priv(dev); - if (dev == sitn->fb_tunnel_dev) { + if (t->dev == sitn->fb_tunnel_dev) { ipv6_addr_set(&t->ip6rd.prefix, htonl(0x20020000), 0, 0, 0); t->ip6rd.relay_prefix = 0; t->ip6rd.prefixlen = 16; @@ -244,13 +244,11 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, if (!create) goto failed; - if (parms->name[0]) { - if (!dev_valid_name(parms->name)) - goto failed; + if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); - } else { + else strcpy(name, "sit%d"); - } + dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, ipip6_tunnel_setup); if (!dev) @@ -477,7 +475,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) ipip6_tunnel_unlink(sitn, tunnel); ipip6_tunnel_del_prl(tunnel, NULL); } - dst_cache_reset(&tunnel->dst_cache); + ip_tunnel_dst_reset_all(tunnel); dev_put(dev); } @@ -562,13 +560,13 @@ static int ipip6_err(struct sk_buff *skb, u32 info) if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { ipv4_update_pmtu(skb, dev_net(skb->dev), info, - t->parms.link, 0, iph->protocol, 0); + t->parms.link, 0, IPPROTO_IPV6, 0); err = 0; goto out; } if (type == ICMP_REDIRECT) { ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0, - iph->protocol, 0); + IPPROTO_IPV6, 0); err = 0; goto out; } @@ -683,15 +681,14 @@ static int ipip6_rcv(struct sk_buff *skb) skb->mac_header = skb->network_header; skb_reset_network_header(skb); IPCB(skb)->flags = 0; - skb->dev = tunnel->dev; + skb->protocol = htons(ETH_P_IPV6); if (packet_is_spoofed(skb, iph, tunnel)) { tunnel->dev->stats.rx_errors++; goto out; } - if (iptunnel_pull_header(skb, 0, htons(ETH_P_IPV6))) - goto out; + __skb_tunnel_rx(skb, tunnel->dev, tunnel->net); err = IP_ECN_decapsulate(iph, skb); if (unlikely(err)) { @@ -1095,12 +1092,11 @@ static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) ipip6_tunnel_link(sitn, t); t->parms.iph.ttl = p->iph.ttl; t->parms.iph.tos = p->iph.tos; - t->parms.iph.frag_off = p->iph.frag_off; if (t->parms.link != p->link) { t->parms.link = p->link; ipip6_tunnel_bind_dev(t->dev); } - dst_cache_reset(&t->dst_cache); + ip_tunnel_dst_reset_all(t); netdev_state_change(t->dev); } @@ -1131,7 +1127,7 @@ static int ipip6_tunnel_update_6rd(struct ip_tunnel *t, t->ip6rd.relay_prefix = relay_prefix; t->ip6rd.prefixlen = ip6rd->prefixlen; t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen; - dst_cache_reset(&t->dst_cache); + ip_tunnel_dst_reset_all(t); netdev_state_change(t->dev); return 0; } @@ -1285,7 +1281,7 @@ ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); break; } - dst_cache_reset(&t->dst_cache); + ip_tunnel_dst_reset_all(t); netdev_state_change(dev); break; @@ -1346,7 +1342,7 @@ static void ipip6_dev_free(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); - dst_cache_destroy(&tunnel->dst_cache); + free_percpu(tunnel->dst_cache); free_percpu(dev->tstats); free_netdev(dev); } @@ -1379,7 +1375,6 @@ static void ipip6_tunnel_setup(struct net_device *dev) static int ipip6_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); - int err; tunnel->dev = dev; tunnel->net = dev_net(dev); @@ -1390,11 +1385,10 @@ static int ipip6_tunnel_init(struct net_device *dev) if (!dev->tstats) return -ENOMEM; - err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); - if (err) { + tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); + if (!tunnel->dst_cache) { free_percpu(dev->tstats); - dev->tstats = NULL; - return err; + return -ENOMEM; } return 0; @@ -1573,13 +1567,6 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev, if (err < 0) return err; - if (tb[IFLA_MTU]) { - u32 mtu = nla_get_u32(tb[IFLA_MTU]); - - if (mtu >= IPV6_MIN_MTU && mtu <= 0xFFF8 - dev->hard_header_len) - dev->mtu = mtu; - } - #ifdef CONFIG_IPV6_SIT_6RD if (ipip6_netlink_6rd_parms(data, &ip6rd)) err = ipip6_tunnel_update_6rd(nt, &ip6rd); diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 3d03be8ee0c2..721bf45fc218 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -244,7 +244,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) treq->snt_synack.v64 = 0; treq->rcv_isn = ntohl(th->seq) - 1; treq->snt_isn = cookie; - treq->txhash = net_tx_rndhash(); /* * We need to lookup the dst_entry to get the correct window size. diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f3ea8795b16f..a66b28dfba82 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -165,13 +165,8 @@ int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, * connect() to INADDR_ANY means loopback (BSD'ism). */ - if (ipv6_addr_any(&usin->sin6_addr)) { - if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) - ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK), - &usin->sin6_addr); - else - usin->sin6_addr = in6addr_loopback; - } + if (ipv6_addr_any(&usin->sin6_addr)) + usin->sin6_addr.s6_addr[15] = 0x1; addr_type = ipv6_addr_type(&usin->sin6_addr); @@ -210,7 +205,7 @@ int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, * TCP over IPv4 */ - if (addr_type & IPV6_ADDR_MAPPED) { + if (addr_type == IPV6_ADDR_MAPPED) { u32 exthdrlen = icsk->icsk_ext_hdr_len; struct sockaddr_in sin; @@ -427,12 +422,10 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, np = inet6_sk(sk); if (type == NDISC_REDIRECT) { - if (!sock_owned_by_user(sk)) { - struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie); + struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie); - if (dst) - dst->ops->redirect(dst, sk, skb); - } + if (dst) + dst->ops->redirect(dst, sk, skb); goto out; } @@ -1086,12 +1079,6 @@ void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV * sk->sk_state == TCP_SYN_RECV -> for Fast Open. */ - - /* RFC 7323 2.3 - * The window field (SEG.WND) of every outgoing segment, with the - * exception of segments, MUST be right-shifted by - * Rcv.Wind.Shift bits: - */ #ifdef CONFIG_MPTCP tcp_v6_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, @@ -1103,10 +1090,9 @@ void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, #else tcp_v6_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, - tcp_rsk(req)->rcv_nxt, - req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale, + tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd, tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if, - tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr), + tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0, 0); #endif } @@ -1145,16 +1131,6 @@ int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) return 0; /* don't send reset */ } -static void tcp_v6_restore_cb(struct sk_buff *skb) -{ - /* We need to move header back to the beginning if xfrm6_policy_check() - * and tcp_v6_fill_cb() are going to be called again. - * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there. - */ - memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6, - sizeof(struct inet6_skb_parm)); -} - #ifndef CONFIG_MPTCP static #endif @@ -1365,10 +1341,8 @@ struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, sk_gfp_atomic(sk, GFP_ATOMIC)); consume_skb(ireq->pktopts); ireq->pktopts = NULL; - if (newnp->pktoptions) { - tcp_v6_restore_cb(newnp->pktoptions); + if (newnp->pktoptions) skb_set_owner_r(newnp->pktoptions, newsk); - } } } @@ -1415,7 +1389,7 @@ int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) return mptcp_v6_do_rcv(sk, skb); #endif - if (tcp_filter(sk, skb)) + if (sk_filter(sk, skb)) goto discard; /* @@ -1519,7 +1493,6 @@ int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) np->flow_label = ip6_flowlabel(ipv6_hdr(opt_skb)); if (ipv6_opt_accepted(sk, opt_skb, &TCP_SKB_CB(opt_skb)->header.h6)) { skb_set_owner_r(opt_skb, sk); - tcp_v6_restore_cb(opt_skb); opt_skb = xchg(&np->pktoptions, opt_skb); } else { __kfree_skb(opt_skb); @@ -1557,8 +1530,16 @@ static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr, TCP_SKB_CB(skb)->sacked = 0; } -#define RC_RETRY_CNT 3 +static void tcp_v6_restore_cb(struct sk_buff *skb) +{ + /* We need to move header back to the beginning if xfrm6_policy_check() + * and tcp_v6_fill_cb() are going to be called again. + */ + memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6, + sizeof(struct inet6_skb_parm)); +} +#define RC_RETRY_CNT 3 static int tcp_v6_rcv(struct sk_buff *skb) { const struct tcphdr *th; @@ -1642,10 +1623,6 @@ static int tcp_v6_rcv(struct sk_buff *skb) reqsk_put(req); goto discard_it; } - if (tcp_checksum_complete(skb)) { - reqsk_put(req); - goto csum_error; - } if (unlikely(sk->sk_state != TCP_LISTEN #ifdef CONFIG_MPTCP && !is_meta_sk(sk) @@ -1717,10 +1694,8 @@ static int tcp_v6_rcv(struct sk_buff *skb) if (tcp_v6_inbound_md5_hash(sk, skb)) goto discard_and_relse; - if (tcp_filter(sk, skb)) + if (sk_filter(sk, skb)) goto discard_and_relse; - th = (const struct tcphdr *)skb->data; - hdr = ipv6_hdr(skb); skb->dev = NULL; @@ -2066,9 +2041,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) destp = ntohs(inet->inet_dport); srcp = ntohs(inet->inet_sport); - if (icsk->icsk_pending == ICSK_TIME_RETRANS || - icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS || - icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) { + if (icsk->icsk_pending == ICSK_TIME_RETRANS) { timer_active = 1; timer_expires = icsk->icsk_timeout; } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) { diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9de5657f0ba9..59fdca3f78d2 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -498,8 +498,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, if (is_udp4) { if (inet->cmsg_flags) - ip_cmsg_recv_offset(msg, skb, - sizeof(struct udphdr), off); + ip_cmsg_recv(msg, skb); } else { if (np->rxopt.all) ip6_datagram_recv_specific_ctl(sk, msg, skb); @@ -650,7 +649,7 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) /* if we're overly short, let UDP handle it */ encap_rcv = ACCESS_ONCE(up->encap_rcv); - if (encap_rcv) { + if (skb->len > sizeof(struct udphdr) && encap_rcv) { int ret; /* Verify checksum before giving to encap */ @@ -1007,7 +1006,6 @@ static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, */ offset = skb_transport_offset(skb); skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); - csum = skb->csum; skb->ip_summed = CHECKSUM_NONE; @@ -1137,10 +1135,6 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) if (addr_len < SIN6_LEN_RFC2133) return -EINVAL; daddr = &sin6->sin6_addr; - if (ipv6_addr_any(daddr) && - ipv6_addr_v4mapped(&np->saddr)) - ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK), - daddr); break; case AF_INET: goto do_udp_sendmsg; diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index 2e3c12eeca07..01582966ffa0 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c @@ -86,7 +86,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, if (uh->check == 0) uh->check = CSUM_MANGLED_0; - skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->ip_summed = CHECKSUM_NONE; /* Check if there is enough headroom to insert fragment header. */ tnl_hlen = skb_tnl_header_len(skb); diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c index 07d36573f50b..0e015906f9ca 100644 --- a/net/ipv6/xfrm6_mode_ro.c +++ b/net/ipv6/xfrm6_mode_ro.c @@ -47,8 +47,6 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb) iph = ipv6_hdr(skb); hdr_len = x->type->hdr_offset(x, skb, &prevhdr); - if (hdr_len < 0) - return hdr_len; skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); skb_set_network_header(skb, -x->props.header_len); skb->transport_header = skb->network_header + hdr_len; diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c index 1d3bbe6e1183..4e344105b3fd 100644 --- a/net/ipv6/xfrm6_mode_transport.c +++ b/net/ipv6/xfrm6_mode_transport.c @@ -28,8 +28,6 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb) iph = ipv6_hdr(skb); hdr_len = x->type->hdr_offset(x, skb, &prevhdr); - if (hdr_len < 0) - return hdr_len; skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); skb_set_network_header(skb, -x->props.header_len); skb->transport_header = skb->network_header + hdr_len; diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 1ca0c2f3d92b..c074771a10f7 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -121,7 +121,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) struct flowi6 *fl6 = &fl->u.ip6; int onlyproto = 0; const struct ipv6hdr *hdr = ipv6_hdr(skb); - u32 offset = sizeof(*hdr); + u16 offset = sizeof(*hdr); struct ipv6_opt_hdr *exthdr; const unsigned char *nh = skb_network_header(skb); u16 nhoff = IP6CB(skb)->nhoff; diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 4a116d766c15..923abd6b3064 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -1024,11 +1024,8 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, } /* Check if we have opened a local TSAP */ - if (!self->tsap) { - err = irda_open_tsap(self, LSAP_ANY, addr->sir_name); - if (err) - goto out; - } + if (!self->tsap) + irda_open_tsap(self, LSAP_ANY, addr->sir_name); /* Move to connecting socket, start sending Connect Requests */ sock->state = SS_CONNECTING; @@ -2227,7 +2224,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, { struct sock *sk = sock->sk; struct irda_sock *self = irda_sk(sk); - struct irda_device_list list = { 0 }; + struct irda_device_list list; struct irda_device_info *discoveries; struct irda_ias_set * ias_opt; /* IAS get/query params */ struct ias_object * ias_obj; /* Object in IAS */ diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 1138eaf5c682..4a7ae32afa09 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -185,12 +185,8 @@ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv, self->magic = IAS_MAGIC; self->mode = mode; - if (mode == IAS_CLIENT) { - if (iriap_register_lsap(self, slsap_sel, mode)) { - kfree(self); - return NULL; - } - } + if (mode == IAS_CLIENT) + iriap_register_lsap(self, slsap_sel, mode); self->confirm = callback; self->priv = priv; diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c index 160dc89335e2..acbe61c7e683 100644 --- a/net/irda/irqueue.c +++ b/net/irda/irqueue.c @@ -383,6 +383,9 @@ EXPORT_SYMBOL(hashbin_new); * for deallocating this structure if it's complex. If not the user can * just supply kfree, which should take care of the job. */ +#ifdef CONFIG_LOCKDEP +static int hashbin_lock_depth = 0; +#endif int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) { irda_queue_t* queue; @@ -393,27 +396,22 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;); /* Synchronize */ - if (hashbin->hb_type & HB_LOCK) - spin_lock_irqsave(&hashbin->hb_spinlock, flags); + if ( hashbin->hb_type & HB_LOCK ) { + spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags, + hashbin_lock_depth++); + } /* * Free the entries in the hashbin, TODO: use hashbin_clear when * it has been shown to work */ for (i = 0; i < HASHBIN_SIZE; i ++ ) { - while (1) { - queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); - - if (!queue) - break; - - if (free_func) { - if (hashbin->hb_type & HB_LOCK) - spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); - free_func(queue); - if (hashbin->hb_type & HB_LOCK) - spin_lock_irqsave(&hashbin->hb_spinlock, flags); - } + queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); + while (queue ) { + if (free_func) + (*free_func)(queue); + queue = dequeue_first( + (irda_queue_t**) &hashbin->hb_queue[i]); } } @@ -422,8 +420,12 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) hashbin->magic = ~HB_MAGIC; /* Release lock */ - if (hashbin->hb_type & HB_LOCK) + if ( hashbin->hb_type & HB_LOCK) { spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); +#ifdef CONFIG_LOCKDEP + hashbin_lock_depth--; +#endif + } /* * Free the hashbin structure diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index aeffb65181f5..20ab7b2ec463 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -2381,11 +2381,9 @@ static int afiucv_iucv_init(void) af_iucv_dev->driver = &af_iucv_driver; err = device_register(af_iucv_dev); if (err) - goto out_iucv_dev; + goto out_driver; return 0; -out_iucv_dev: - put_device(af_iucv_dev); out_driver: driver_unregister(&af_iucv_driver); out_iucv: diff --git a/net/key/af_key.c b/net/key/af_key.c index 3ba903ff2bb0..f9c9ecb0cdd3 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -63,13 +63,8 @@ struct pfkey_sock { } u; struct sk_buff *skb; } dump; - struct mutex dump_lock; }; -static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, - xfrm_address_t *saddr, xfrm_address_t *daddr, - u16 *family); - static inline struct pfkey_sock *pfkey_sk(struct sock *sk) { return (struct pfkey_sock *)sk; @@ -144,7 +139,6 @@ static int pfkey_create(struct net *net, struct socket *sock, int protocol, { struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); struct sock *sk; - struct pfkey_sock *pfk; int err; if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) @@ -159,9 +153,6 @@ static int pfkey_create(struct net *net, struct socket *sock, int protocol, if (sk == NULL) goto out; - pfk = pfkey_sk(sk); - mutex_init(&pfk->dump_lock); - sock->ops = &pfkey_ops; sock_init_data(sock, sk); @@ -228,7 +219,7 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, #define BROADCAST_ONE 1 #define BROADCAST_REGISTERED 2 #define BROADCAST_PROMISC_ONLY 4 -static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, +static int pfkey_broadcast(struct sk_buff *skb, int broadcast_flags, struct sock *one_sk, struct net *net) { @@ -278,7 +269,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, rcu_read_unlock(); if (one_sk != NULL) - err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk); + err = pfkey_broadcast_one(skb, &skb2, GFP_KERNEL, one_sk); kfree_skb(skb2); kfree_skb(skb); @@ -290,36 +281,23 @@ static int pfkey_do_dump(struct pfkey_sock *pfk) struct sadb_msg *hdr; int rc; - mutex_lock(&pfk->dump_lock); - if (!pfk->dump.dump) { - rc = 0; - goto out; - } - rc = pfk->dump.dump(pfk); - if (rc == -ENOBUFS) { - rc = 0; - goto out; - } + if (rc == -ENOBUFS) + return 0; if (pfk->dump.skb) { - if (!pfkey_can_dump(&pfk->sk)) { - rc = 0; - goto out; - } + if (!pfkey_can_dump(&pfk->sk)) + return 0; hdr = (struct sadb_msg *) pfk->dump.skb->data; hdr->sadb_msg_seq = 0; hdr->sadb_msg_errno = rc; - pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, + pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE, &pfk->sk, sock_net(&pfk->sk)); pfk->dump.skb = NULL; } pfkey_terminate_dump(pfk); - -out: - mutex_unlock(&pfk->dump_lock); return rc; } @@ -355,7 +333,7 @@ static int pfkey_error(const struct sadb_msg *orig, int err, struct sock *sk) hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); - pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ONE, sk, sock_net(sk)); + pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk)); return 0; } @@ -401,11 +379,6 @@ static int verify_address_len(const void *p) #endif int len; - if (sp->sadb_address_len < - DIV_ROUND_UP(sizeof(*sp) + offsetofend(typeof(*addr), sa_family), - sizeof(uint64_t))) - return -EINVAL; - switch (addr->sa_family) { case AF_INET: len = DIV_ROUND_UP(sizeof(*sp) + sizeof(*sin), sizeof(uint64_t)); @@ -437,24 +410,6 @@ static int verify_address_len(const void *p) return 0; } -static inline int sadb_key_len(const struct sadb_key *key) -{ - int key_bytes = DIV_ROUND_UP(key->sadb_key_bits, 8); - - return DIV_ROUND_UP(sizeof(struct sadb_key) + key_bytes, - sizeof(uint64_t)); -} - -static int verify_key_len(const void *p) -{ - const struct sadb_key *key = p; - - if (sadb_key_len(key) > key->sadb_key_len) - return -EINVAL; - - return 0; -} - static inline int pfkey_sec_ctx_len(const struct sadb_x_sec_ctx *sec_ctx) { return DIV_ROUND_UP(sizeof(struct sadb_x_sec_ctx) + @@ -534,9 +489,6 @@ static int parse_exthdrs(struct sk_buff *skb, const struct sadb_msg *hdr, void * uint16_t ext_type; int ext_len; - if (len < sizeof(*ehdr)) - return -EINVAL; - ext_len = ehdr->sadb_ext_len; ext_len *= sizeof(uint64_t); ext_type = ehdr->sadb_ext_type; @@ -551,25 +503,16 @@ static int parse_exthdrs(struct sk_buff *skb, const struct sadb_msg *hdr, void * return -EINVAL; if (ext_hdrs[ext_type-1] != NULL) return -EINVAL; - switch (ext_type) { - case SADB_EXT_ADDRESS_SRC: - case SADB_EXT_ADDRESS_DST: - case SADB_EXT_ADDRESS_PROXY: - case SADB_X_EXT_NAT_T_OA: + if (ext_type == SADB_EXT_ADDRESS_SRC || + ext_type == SADB_EXT_ADDRESS_DST || + ext_type == SADB_EXT_ADDRESS_PROXY || + ext_type == SADB_X_EXT_NAT_T_OA) { if (verify_address_len(p)) return -EINVAL; - break; - case SADB_X_EXT_SEC_CTX: + } + if (ext_type == SADB_X_EXT_SEC_CTX) { if (verify_sec_ctx_len(p)) return -EINVAL; - break; - case SADB_EXT_KEY_AUTH: - case SADB_EXT_KEY_ENCRYPT: - if (verify_key_len(p)) - return -EINVAL; - break; - default: - break; } ext_hdrs[ext_type-1] = (void *) p; } @@ -1138,12 +1081,14 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, key = ext_hdrs[SADB_EXT_KEY_AUTH - 1]; if (key != NULL && sa->sadb_sa_auth != SADB_X_AALG_NULL && - key->sadb_key_bits == 0) + ((key->sadb_key_bits+7) / 8 == 0 || + (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t))) return ERR_PTR(-EINVAL); key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1]; if (key != NULL && sa->sadb_sa_encrypt != SADB_EALG_NULL && - key->sadb_key_bits == 0) + ((key->sadb_key_bits+7) / 8 == 0 || + (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t))) return ERR_PTR(-EINVAL); x = xfrm_state_alloc(net); @@ -1190,7 +1135,6 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, goto out; } - err = -ENOBUFS; key = ext_hdrs[SADB_EXT_KEY_AUTH - 1]; if (sa->sadb_sa_auth) { int keysize = 0; @@ -1202,10 +1146,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, if (key) keysize = (key->sadb_key_bits + 7) / 8; x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL); - if (!x->aalg) { - err = -ENOMEM; + if (!x->aalg) goto out; - } strcpy(x->aalg->alg_name, a->name); x->aalg->alg_key_len = 0; if (key) { @@ -1224,10 +1166,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, goto out; } x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL); - if (!x->calg) { - err = -ENOMEM; + if (!x->calg) goto out; - } strcpy(x->calg->alg_name, a->name); x->props.calgo = sa->sadb_sa_encrypt; } else { @@ -1241,10 +1181,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, if (key) keysize = (key->sadb_key_bits + 7) / 8; x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL); - if (!x->ealg) { - err = -ENOMEM; + if (!x->ealg) goto out; - } strcpy(x->ealg->alg_name, a->name); x->ealg->alg_key_len = 0; if (key) { @@ -1289,10 +1227,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, struct xfrm_encap_tmpl *natt; x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL); - if (!x->encap) { - err = -ENOMEM; + if (!x->encap) goto out; - } natt = x->encap; n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]; @@ -1429,7 +1365,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_ xfrm_state_put(x); - pfkey_broadcast(resp_skb, GFP_KERNEL, BROADCAST_ONE, sk, net); + pfkey_broadcast(resp_skb, BROADCAST_ONE, sk, net); return 0; } @@ -1516,7 +1452,7 @@ static int key_notify_sa(struct xfrm_state *x, const struct km_event *c) hdr->sadb_msg_seq = c->seq; hdr->sadb_msg_pid = c->portid; - pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xs_net(x)); + pfkey_broadcast(skb, BROADCAST_ALL, NULL, xs_net(x)); return 0; } @@ -1629,7 +1565,7 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, const struct sadb_msg out_hdr->sadb_msg_reserved = 0; out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; - pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk)); + pfkey_broadcast(out_skb, BROADCAST_ONE, sk, sock_net(sk)); return 0; } @@ -1734,8 +1670,8 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sad return -ENOBUFS; } - pfkey_broadcast(supp_skb, GFP_KERNEL, BROADCAST_REGISTERED, sk, - sock_net(sk)); + pfkey_broadcast(supp_skb, BROADCAST_REGISTERED, sk, sock_net(sk)); + return 0; } @@ -1753,8 +1689,7 @@ static int unicast_flush_resp(struct sock *sk, const struct sadb_msg *ihdr) hdr->sadb_msg_errno = (uint8_t) 0; hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); - return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk, - sock_net(sk)); + return pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk)); } static int key_notify_sa_flush(const struct km_event *c) @@ -1775,7 +1710,7 @@ static int key_notify_sa_flush(const struct km_event *c) hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); hdr->sadb_msg_reserved = 0; - pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); + pfkey_broadcast(skb, BROADCAST_ALL, NULL, c->net); return 0; } @@ -1832,7 +1767,7 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr) out_hdr->sadb_msg_pid = pfk->dump.msg_portid; if (pfk->dump.skb) - pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, + pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE, &pfk->sk, sock_net(&pfk->sk)); pfk->dump.skb = out_skb; @@ -1858,26 +1793,19 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms struct xfrm_address_filter *filter = NULL; struct pfkey_sock *pfk = pfkey_sk(sk); - mutex_lock(&pfk->dump_lock); - if (pfk->dump.dump != NULL) { - mutex_unlock(&pfk->dump_lock); + if (pfk->dump.dump != NULL) return -EBUSY; - } proto = pfkey_satype2proto(hdr->sadb_msg_satype); - if (proto == 0) { - mutex_unlock(&pfk->dump_lock); + if (proto == 0) return -EINVAL; - } if (ext_hdrs[SADB_X_EXT_FILTER - 1]) { struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1]; filter = kmalloc(sizeof(*filter), GFP_KERNEL); - if (filter == NULL) { - mutex_unlock(&pfk->dump_lock); + if (filter == NULL) return -ENOMEM; - } memcpy(&filter->saddr, &xfilter->sadb_x_filter_saddr, sizeof(xfrm_address_t)); @@ -1893,7 +1821,6 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms pfk->dump.dump = pfkey_dump_sa; pfk->dump.done = pfkey_dump_sa_done; xfrm_state_walk_init(&pfk->dump.u.state, proto, filter); - mutex_unlock(&pfk->dump_lock); return pfkey_do_dump(pfk); } @@ -1920,7 +1847,7 @@ static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, const struct sadb new_hdr->sadb_msg_errno = 0; } - pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ALL, NULL, sock_net(sk)); + pfkey_broadcast(skb, BROADCAST_ALL, NULL, sock_net(sk)); return 0; } @@ -1986,14 +1913,19 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) /* addresses present only in tunnel mode */ if (t->mode == XFRM_MODE_TUNNEL) { - int err; + u8 *sa = (u8 *) (rq + 1); + int family, socklen; - err = parse_sockaddr_pair( - (struct sockaddr *)(rq + 1), - rq->sadb_x_ipsecrequest_len - sizeof(*rq), - &t->saddr, &t->id.daddr, &t->encap_family); - if (err) - return err; + family = pfkey_sockaddr_extract((struct sockaddr *)sa, + &t->saddr); + if (!family) + return -EINVAL; + + socklen = pfkey_sockaddr_len(family); + if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen), + &t->id.daddr) != family) + return -EINVAL; + t->encap_family = family; } else t->encap_family = xp->family; @@ -2013,11 +1945,7 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol) if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy)) return -EINVAL; - while (len >= sizeof(*rq)) { - if (len < rq->sadb_x_ipsecrequest_len || - rq->sadb_x_ipsecrequest_len < sizeof(*rq)) - return -EINVAL; - + while (len >= sizeof(struct sadb_x_ipsecrequest)) { if ((err = parse_ipsecrequest(xp, rq)) < 0) return err; len -= rq->sadb_x_ipsecrequest_len; @@ -2253,7 +2181,7 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, const struct km_ev out_hdr->sadb_msg_errno = 0; out_hdr->sadb_msg_seq = c->seq; out_hdr->sadb_msg_pid = c->portid; - pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xp_net(xp)); + pfkey_broadcast(out_skb, BROADCAST_ALL, NULL, xp_net(xp)); return 0; } @@ -2473,13 +2401,14 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, const struc out_hdr->sadb_msg_errno = 0; out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; - pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, xp_net(xp)); + pfkey_broadcast(out_skb, BROADCAST_ONE, sk, xp_net(xp)); err = 0; out: return err; } +#ifdef CONFIG_NET_KEY_MIGRATE static int pfkey_sockaddr_pair_size(sa_family_t family) { return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); @@ -2491,7 +2420,7 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, { int af, socklen; - if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) + if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) return -EINVAL; af = pfkey_sockaddr_extract(sa, saddr); @@ -2507,7 +2436,6 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, return 0; } -#ifdef CONFIG_NET_KEY_MIGRATE static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, struct xfrm_migrate *m) { @@ -2515,14 +2443,13 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, struct sadb_x_ipsecrequest *rq2; int mode; - if (len < sizeof(*rq1) || - len < rq1->sadb_x_ipsecrequest_len || - rq1->sadb_x_ipsecrequest_len < sizeof(*rq1)) + if (len <= sizeof(struct sadb_x_ipsecrequest) || + len < rq1->sadb_x_ipsecrequest_len) return -EINVAL; /* old endoints */ err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1), - rq1->sadb_x_ipsecrequest_len - sizeof(*rq1), + rq1->sadb_x_ipsecrequest_len, &m->old_saddr, &m->old_daddr, &m->old_family); if (err) @@ -2531,14 +2458,13 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len); len -= rq1->sadb_x_ipsecrequest_len; - if (len <= sizeof(*rq2) || - len < rq2->sadb_x_ipsecrequest_len || - rq2->sadb_x_ipsecrequest_len < sizeof(*rq2)) + if (len <= sizeof(struct sadb_x_ipsecrequest) || + len < rq2->sadb_x_ipsecrequest_len) return -EINVAL; /* new endpoints */ err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1), - rq2->sadb_x_ipsecrequest_len - sizeof(*rq2), + rq2->sadb_x_ipsecrequest_len, &m->new_saddr, &m->new_daddr, &m->new_family); if (err) @@ -2729,7 +2655,7 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr) out_hdr->sadb_msg_pid = pfk->dump.msg_portid; if (pfk->dump.skb) - pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, + pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE, &pfk->sk, sock_net(&pfk->sk)); pfk->dump.skb = out_skb; @@ -2753,18 +2679,14 @@ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, const struct sadb { struct pfkey_sock *pfk = pfkey_sk(sk); - mutex_lock(&pfk->dump_lock); - if (pfk->dump.dump != NULL) { - mutex_unlock(&pfk->dump_lock); + if (pfk->dump.dump != NULL) return -EBUSY; - } pfk->dump.msg_version = hdr->sadb_msg_version; pfk->dump.msg_portid = hdr->sadb_msg_pid; pfk->dump.dump = pfkey_dump_sp; pfk->dump.done = pfkey_dump_sp_done; xfrm_policy_walk_init(&pfk->dump.u.policy, XFRM_POLICY_TYPE_MAIN); - mutex_unlock(&pfk->dump_lock); return pfkey_do_dump(pfk); } @@ -2786,7 +2708,7 @@ static int key_notify_policy_flush(const struct km_event *c) hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); hdr->sadb_msg_reserved = 0; - pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); + pfkey_broadcast(skb_out, BROADCAST_ALL, NULL, c->net); return 0; } @@ -2848,7 +2770,7 @@ static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb void *ext_hdrs[SADB_EXT_MAX]; int err; - pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL, + pfkey_broadcast(skb_clone(skb, GFP_KERNEL), BROADCAST_PROMISC_ONLY, NULL, sock_net(sk)); memset(ext_hdrs, 0, sizeof(ext_hdrs)); @@ -3070,8 +2992,7 @@ static int key_notify_sa_expire(struct xfrm_state *x, const struct km_event *c) out_hdr->sadb_msg_seq = 0; out_hdr->sadb_msg_pid = 0; - pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, - xs_net(x)); + pfkey_broadcast(out_skb, BROADCAST_REGISTERED, NULL, xs_net(x)); return 0; } @@ -3261,8 +3182,7 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_ctx->ctx_len); } - return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, - xs_net(x)); + return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x)); } static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, @@ -3330,7 +3250,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, p += pol->sadb_x_policy_len*8; sec_ctx = (struct sadb_x_sec_ctx *)p; if (len < pol->sadb_x_policy_len*8 + - sec_ctx->sadb_x_sec_len*8) { + sec_ctx->sadb_x_sec_len) { *dir = -EINVAL; goto out; } @@ -3460,8 +3380,7 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, n_port->sadb_x_nat_t_port_port = sport; n_port->sadb_x_nat_t_port_reserved = 0; - return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, - xs_net(x)); + return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x)); } #ifdef CONFIG_NET_KEY_MIGRATE @@ -3653,7 +3572,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, } /* broadcast migrate message to sockets */ - pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net); + pfkey_broadcast(skb, BROADCAST_ALL, NULL, &init_net); return 0; diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 591d18785285..afca2eb4dfa7 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -278,8 +278,7 @@ struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunn } EXPORT_SYMBOL_GPL(l2tp_session_find); -struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth, - bool do_ref) +struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth) { int hash; struct l2tp_session *session; @@ -289,9 +288,6 @@ struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth, for (hash = 0; hash < L2TP_HASH_SIZE; hash++) { hlist_for_each_entry(session, &tunnel->session_hlist[hash], hlist) { if (++count > nth) { - l2tp_session_inc_refcount(session); - if (do_ref && session->ref) - session->ref(session); read_unlock_bh(&tunnel->hlist_lock); return session; } @@ -302,7 +298,7 @@ struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth, return NULL; } -EXPORT_SYMBOL_GPL(l2tp_session_get_nth); +EXPORT_SYMBOL_GPL(l2tp_session_find_nth); /* Lookup a session by interface name. * This is very inefficient but is only used by management interfaces. @@ -1145,7 +1141,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len /* Get routing info from the tunnel socket */ skb_dst_drop(skb); - skb_dst_set(skb, sk_dst_check(sk, 0)); + skb_dst_set(skb, dst_clone(__sk_dst_check(sk, 0))); inet = inet_sk(sk); fl = &inet->cork.fl; @@ -1321,9 +1317,6 @@ static void l2tp_tunnel_del_work(struct work_struct *work) struct sock *sk = NULL; tunnel = container_of(work, struct l2tp_tunnel, del_work); - - l2tp_tunnel_closeall(tunnel); - sk = l2tp_tunnel_sock_lookup(tunnel); if (!sk) goto out; @@ -1518,14 +1511,9 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 encap = cfg->encap; /* Quick sanity checks */ - err = -EPROTONOSUPPORT; - if (sk->sk_type != SOCK_DGRAM) { - pr_debug("tunl %hu: fd %d wrong socket type\n", - tunnel_id, fd); - goto err; - } switch (encap) { case L2TP_ENCAPTYPE_UDP: + err = -EPROTONOSUPPORT; if (sk->sk_protocol != IPPROTO_UDP) { pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n", tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP); @@ -1533,6 +1521,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 } break; case L2TP_ENCAPTYPE_IP: + err = -EPROTONOSUPPORT; if (sk->sk_protocol != IPPROTO_L2TP) { pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n", tunnel_id, fd, sk->sk_protocol, IPPROTO_L2TP); @@ -1592,7 +1581,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ tunnel->encap = encap; if (encap == L2TP_ENCAPTYPE_UDP) { - struct udp_tunnel_sock_cfg udp_cfg = { }; + struct udp_tunnel_sock_cfg udp_cfg; udp_cfg.sk_user_data = tunnel; udp_cfg.encap_type = UDP_ENCAP_L2TPINUDP; @@ -1647,12 +1636,15 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create); /* This function is used by the netlink TUNNEL_DELETE command. */ -void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) +int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) { - if (!test_and_set_bit(0, &tunnel->dead)) { - l2tp_tunnel_inc_refcount(tunnel); - queue_work(l2tp_wq, &tunnel->del_work); + l2tp_tunnel_inc_refcount(tunnel); + l2tp_tunnel_closeall(tunnel); + if (false == queue_work(l2tp_wq, &tunnel->del_work)) { + l2tp_tunnel_dec_refcount(tunnel); + return 1; } + return 0; } EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); @@ -1860,7 +1852,7 @@ static __net_exit void l2tp_exit_net(struct net *net) rcu_read_lock_bh(); list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { - l2tp_tunnel_delete(tunnel); + (void)l2tp_tunnel_delete(tunnel); } rcu_read_unlock_bh(); } diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 9cf546846edb..5871537af387 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -169,9 +169,6 @@ struct l2tp_tunnel_cfg { struct l2tp_tunnel { int magic; /* Should be L2TP_TUNNEL_MAGIC */ - - unsigned long dead; - struct rcu_head rcu; rwlock_t hlist_lock; /* protect session_hlist */ struct hlist_head session_hlist[L2TP_HASH_SIZE]; @@ -246,8 +243,7 @@ static inline struct l2tp_tunnel *l2tp_sock_to_tunnel(struct sock *sk) struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id); -struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth, - bool do_ref); +struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth); struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname); struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id); struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth); @@ -256,7 +252,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp); void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); -void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); +int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, @@ -277,7 +273,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops); void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type); -int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg); /* Session reference counts. Incremented when code obtains a reference * to a session. diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c index d100aed3d06f..2d6760a2ae34 100644 --- a/net/l2tp/l2tp_debugfs.c +++ b/net/l2tp/l2tp_debugfs.c @@ -53,7 +53,7 @@ static void l2tp_dfs_next_tunnel(struct l2tp_dfs_seq_data *pd) static void l2tp_dfs_next_session(struct l2tp_dfs_seq_data *pd) { - pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true); + pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx); pd->session_idx++; if (pd->session == NULL) { @@ -238,14 +238,10 @@ static int l2tp_dfs_seq_show(struct seq_file *m, void *v) } /* Show the tunnel or session context */ - if (!pd->session) { + if (pd->session == NULL) l2tp_dfs_seq_tunnel_show(m, pd->tunnel); - } else { + else l2tp_dfs_seq_session_show(m, pd->session); - if (pd->session->deref) - pd->session->deref(pd->session); - l2tp_session_dec_refcount(pd->session); - } out: return 0; diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 48ab93842322..d0e906d39642 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -11,7 +11,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include #include #include #include @@ -383,7 +382,7 @@ static int l2tp_ip_backlog_recv(struct sock *sk, struct sk_buff *skb) drop: IP_INC_STATS(sock_net(sk), IPSTATS_MIB_INDISCARDS); kfree_skb(skb); - return 0; + return -1; } /* Userspace will call sendmsg() on the tunnel socket to send L2TP @@ -556,30 +555,6 @@ static int l2tp_ip_recvmsg(struct sock *sk, struct msghdr *msg, return err ? err : copied; } -int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg) -{ - struct sk_buff *skb; - int amount; - - switch (cmd) { - case SIOCOUTQ: - amount = sk_wmem_alloc_get(sk); - break; - case SIOCINQ: - spin_lock_bh(&sk->sk_receive_queue.lock); - skb = skb_peek(&sk->sk_receive_queue); - amount = skb ? skb->len : 0; - spin_unlock_bh(&sk->sk_receive_queue.lock); - break; - - default: - return -ENOIOCTLCMD; - } - - return put_user(amount, (int __user *)arg); -} -EXPORT_SYMBOL(l2tp_ioctl); - static struct proto l2tp_ip_prot = { .name = "L2TP/IP", .owner = THIS_MODULE, @@ -588,7 +563,7 @@ static struct proto l2tp_ip_prot = { .bind = l2tp_ip_bind, .connect = l2tp_ip_connect, .disconnect = l2tp_ip_disconnect, - .ioctl = l2tp_ioctl, + .ioctl = udp_ioctl, .destroy = l2tp_ip_destroy_sock, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index c8f483cd2ca9..0289208b0346 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -715,7 +715,7 @@ static struct proto l2tp_ip6_prot = { .bind = l2tp_ip6_bind, .connect = l2tp_ip6_connect, .disconnect = l2tp_ip6_disconnect, - .ioctl = l2tp_ioctl, + .ioctl = udp_ioctl, .destroy = l2tp_ip6_destroy_sock, .setsockopt = ipv6_setsockopt, .getsockopt = ipv6_getsockopt, diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index fb3248ff8b48..2caaa84ce92d 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -285,7 +285,7 @@ static int l2tp_nl_cmd_tunnel_delete(struct sk_buff *skb, struct genl_info *info l2tp_tunnel_notify(&l2tp_nl_family, info, tunnel, L2TP_CMD_TUNNEL_DELETE); - l2tp_tunnel_delete(tunnel); + (void) l2tp_tunnel_delete(tunnel); out: return ret; @@ -827,7 +827,7 @@ static int l2tp_nl_cmd_session_dump(struct sk_buff *skb, struct netlink_callback goto out; } - session = l2tp_session_get_nth(tunnel, si, false); + session = l2tp_session_find_nth(tunnel, si); if (session == NULL) { ti++; tunnel = NULL; @@ -837,11 +837,8 @@ static int l2tp_nl_cmd_session_dump(struct sk_buff *skb, struct netlink_callback if (l2tp_nl_session_send(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NLM_F_MULTI, - session, L2TP_CMD_SESSION_GET) < 0) { - l2tp_session_dec_refcount(session); + session, L2TP_CMD_SESSION_GET) < 0) break; - } - l2tp_session_dec_refcount(session); si++; } diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 2764c4bd072c..1ad18c55064c 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -467,10 +467,6 @@ static void pppol2tp_session_close(struct l2tp_session *session) static void pppol2tp_session_destruct(struct sock *sk) { struct l2tp_session *session = sk->sk_user_data; - - skb_queue_purge(&sk->sk_receive_queue); - skb_queue_purge(&sk->sk_write_queue); - if (session) { sk->sk_user_data = NULL; BUG_ON(session->magic != L2TP_SESSION_MAGIC); @@ -509,6 +505,9 @@ static int pppol2tp_release(struct socket *sock) l2tp_session_queue_purge(session); sock_put(sk); } + skb_queue_purge(&sk->sk_receive_queue); + skb_queue_purge(&sk->sk_write_queue); + release_sock(sk); /* This will delete the session context via @@ -606,13 +605,6 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, lock_sock(sk); error = -EINVAL; - - if (sockaddr_len != sizeof(struct sockaddr_pppol2tp) && - sockaddr_len != sizeof(struct sockaddr_pppol2tpv3) && - sockaddr_len != sizeof(struct sockaddr_pppol2tpin6) && - sockaddr_len != sizeof(struct sockaddr_pppol2tpv3in6)) - goto end; - if (sp->sa_protocol != PX_PROTO_OL2TP) goto end; @@ -1022,9 +1014,6 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session, session->name, cmd, arg); sk = ps->sock; - if (!sk) - return -EBADR; - sock_hold(sk); switch (cmd) { @@ -1585,7 +1574,7 @@ static void pppol2tp_next_tunnel(struct net *net, struct pppol2tp_seq_data *pd) static void pppol2tp_next_session(struct net *net, struct pppol2tp_seq_data *pd) { - pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true); + pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx); pd->session_idx++; if (pd->session == NULL) { @@ -1712,14 +1701,10 @@ static int pppol2tp_seq_show(struct seq_file *m, void *v) /* Show the tunnel or session context. */ - if (!pd->session) { + if (pd->session == NULL) pppol2tp_seq_tunnel_show(m, pd->tunnel); - } else { + else pppol2tp_seq_session_show(m, pd->session); - if (pd->session->deref) - pd->session->deref(pd->session); - l2tp_session_dec_refcount(pd->session); - } out: return 0; @@ -1878,4 +1863,4 @@ MODULE_DESCRIPTION("PPP over L2TP over UDP"); MODULE_LICENSE("GPL"); MODULE_VERSION(PPPOL2TP_DRV_VERSION); MODULE_ALIAS("pppox-proto-" __stringify(PX_PROTO_OL2TP)); -MODULE_ALIAS_L2TP_PWTYPE(7); +MODULE_ALIAS_L2TP_PWTYPE(11); diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 83e8a295c806..bb8edb9ef506 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -197,19 +197,9 @@ static int llc_ui_release(struct socket *sock) llc->laddr.lsap, llc->daddr.lsap); if (!llc_send_disc(sk)) llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo); - if (!sock_flag(sk, SOCK_ZAPPED)) { - struct llc_sap *sap = llc->sap; - - /* Hold this for release_sock(), so that llc_backlog_rcv() - * could still use it. - */ - llc_sap_hold(sap); + if (!sock_flag(sk, SOCK_ZAPPED)) llc_sap_remove_socket(llc->sap, sk); - release_sock(sk); - llc_sap_put(sap); - } else { - release_sock(sk); - } + release_sock(sk); if (llc->dev) dev_put(llc->dev); sock_put(sk); @@ -319,8 +309,6 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) int rc = -EINVAL; dprintk("%s: binding %02X\n", __func__, addr->sllc_sap); - - lock_sock(sk); if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr))) goto out; rc = -EAFNOSUPPORT; @@ -392,7 +380,6 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) out_put: llc_sap_put(sap); out: - release_sock(sk); return rc; } @@ -926,9 +913,6 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) if (size > llc->dev->mtu) size = llc->dev->mtu; copied = size - hdrlen; - rc = -EINVAL; - if (copied < 0) - goto release; release_sock(sk); skb = sock_alloc_send_skb(sk, size, noblock, &rc); lock_sock(sk); diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 4b60f68cb492..ea225bd2672c 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -389,7 +389,7 @@ static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb) llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); if (likely(!rc)) { - rc = llc_conn_send_pdu(sk, skb); + llc_conn_send_pdu(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb); } return rc; @@ -916,7 +916,7 @@ static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk, llc_pdu_init_as_i_cmd(skb, llc->ack_pf, llc->vS, llc->vR); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); if (likely(!rc)) { - rc = llc_conn_send_pdu(sk, skb); + llc_conn_send_pdu(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb); } return rc; @@ -935,17 +935,14 @@ static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk, int llc_conn_ac_send_i_as_ack(struct sock *sk, struct sk_buff *skb) { struct llc_sock *llc = llc_sk(sk); - int ret; if (llc->ack_must_be_send) { - ret = llc_conn_ac_send_i_rsp_f_set_ackpf(sk, skb); + llc_conn_ac_send_i_rsp_f_set_ackpf(sk, skb); llc->ack_must_be_send = 0 ; llc->ack_pf = 0; - } else { - ret = llc_conn_ac_send_i_cmd_p_set_0(sk, skb); - } - - return ret; + } else + llc_conn_ac_send_i_cmd_p_set_0(sk, skb); + return 0; } /** @@ -1099,7 +1096,14 @@ int llc_conn_ac_inc_tx_win_size(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_stop_all_timers(struct sock *sk, struct sk_buff *skb) { - llc_sk_stop_all_timers(sk, false); + struct llc_sock *llc = llc_sk(sk); + + del_timer(&llc->pf_cycle_timer.timer); + del_timer(&llc->ack_timer.timer); + del_timer(&llc->rej_sent_timer.timer); + del_timer(&llc->busy_state_timer.timer); + llc->ack_must_be_send = 0; + llc->ack_pf = 0; return 0; } diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 79c346fd859b..3e821daf9dd4 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -30,7 +30,7 @@ #endif static int llc_find_offset(int state, int ev_type); -static int llc_conn_send_pdus(struct sock *sk, struct sk_buff *skb); +static void llc_conn_send_pdus(struct sock *sk); static int llc_conn_service(struct sock *sk, struct sk_buff *skb); static int llc_exec_conn_trans_actions(struct sock *sk, struct llc_conn_state_trans *trans, @@ -193,11 +193,11 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) return rc; } -int llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb) +void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb) { /* queue PDU to send to MAC layer */ skb_queue_tail(&sk->sk_write_queue, skb); - return llc_conn_send_pdus(sk, skb); + llc_conn_send_pdus(sk); } /** @@ -255,7 +255,7 @@ void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit) if (howmany_resend > 0) llc->vS = (llc->vS + 1) % LLC_2_SEQ_NBR_MODULO; /* any PDUs to re-send are queued up; start sending to MAC */ - llc_conn_send_pdus(sk, NULL); + llc_conn_send_pdus(sk); out:; } @@ -296,7 +296,7 @@ void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit) if (howmany_resend > 0) llc->vS = (llc->vS + 1) % LLC_2_SEQ_NBR_MODULO; /* any PDUs to re-send are queued up; start sending to MAC */ - llc_conn_send_pdus(sk, NULL); + llc_conn_send_pdus(sk); out:; } @@ -340,16 +340,12 @@ int llc_conn_remove_acked_pdus(struct sock *sk, u8 nr, u16 *how_many_unacked) /** * llc_conn_send_pdus - Sends queued PDUs * @sk: active connection - * @hold_skb: the skb held by caller, or NULL if does not care * - * Sends queued pdus to MAC layer for transmission. When @hold_skb is - * NULL, always return 0. Otherwise, return 0 if @hold_skb is sent - * successfully, or 1 for failure. + * Sends queued pdus to MAC layer for transmission. */ -static int llc_conn_send_pdus(struct sock *sk, struct sk_buff *hold_skb) +static void llc_conn_send_pdus(struct sock *sk) { struct sk_buff *skb; - int ret = 0; while ((skb = skb_dequeue(&sk->sk_write_queue)) != NULL) { struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); @@ -361,20 +357,10 @@ static int llc_conn_send_pdus(struct sock *sk, struct sk_buff *hold_skb) skb_queue_tail(&llc_sk(sk)->pdu_unack_q, skb); if (!skb2) break; - dev_queue_xmit(skb2); - } else { - bool is_target = skb == hold_skb; - int rc; - - if (is_target) - skb_get(skb); - rc = dev_queue_xmit(skb); - if (is_target) - ret = rc; + skb = skb2; } + dev_queue_xmit(skb); } - - return ret; } /** @@ -835,10 +821,7 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) * another trick required to cope with how the PROCOM state * machine works. -acme */ - skb_orphan(skb); - sock_hold(sk); skb->sk = sk; - skb->destructor = sock_efree; } if (!sock_owned_by_user(sk)) llc_conn_rcv(sk, skb); @@ -965,26 +948,6 @@ struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority, struct pr return sk; } -void llc_sk_stop_all_timers(struct sock *sk, bool sync) -{ - struct llc_sock *llc = llc_sk(sk); - - if (sync) { - del_timer_sync(&llc->pf_cycle_timer.timer); - del_timer_sync(&llc->ack_timer.timer); - del_timer_sync(&llc->rej_sent_timer.timer); - del_timer_sync(&llc->busy_state_timer.timer); - } else { - del_timer(&llc->pf_cycle_timer.timer); - del_timer(&llc->ack_timer.timer); - del_timer(&llc->rej_sent_timer.timer); - del_timer(&llc->busy_state_timer.timer); - } - - llc->ack_must_be_send = 0; - llc->ack_pf = 0; -} - /** * llc_sk_free - Frees a LLC socket * @sk - socket to free @@ -997,7 +960,7 @@ void llc_sk_free(struct sock *sk) llc->state = LLC_CONN_OUT_OF_SVC; /* Stop all (possibly) running timers */ - llc_sk_stop_all_timers(sk, true); + llc_conn_ac_stop_all_timers(sk, NULL); #ifdef DEBUG_LLC_CONN_ALLOC printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __func__, skb_queue_len(&llc->pdu_unack_q), diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index e896a2c53b12..842851cef698 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c @@ -73,8 +73,8 @@ struct llc_sap *llc_sap_find(unsigned char sap_value) rcu_read_lock_bh(); sap = __llc_sap_find(sap_value); - if (!sap || !llc_sap_hold_safe(sap)) - sap = NULL; + if (sap) + llc_sap_hold(sap); rcu_read_unlock_bh(); return sap; } diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 5404d0d195cc..d0e1e804ebd7 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -290,10 +290,7 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb, ev->type = LLC_SAP_EV_TYPE_PDU; ev->reason = 0; - skb_orphan(skb); - sock_hold(sk); skb->sk = sk; - skb->destructor = sock_efree; llc_sap_state_process(sap, skb); } diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index a830356b94ac..367784be5df2 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -7,7 +7,6 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007, Michael Wu * Copyright 2007-2010, Intel Corporation - * Copyright(c) 2015 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -62,14 +61,6 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, { struct ieee80211_local *local = sta->local; struct tid_ampdu_rx *tid_rx; - struct ieee80211_ampdu_params params = { - .sta = &sta->sta, - .action = IEEE80211_AMPDU_RX_STOP, - .tid = tid, - .amsdu = false, - .timeout = 0, - .ssn = 0, - }; lockdep_assert_held(&sta->ampdu_mlme.mtx); @@ -87,7 +78,8 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", (int)reason); - if (drv_ampdu_action(local, sta->sdata, ¶ms)) + if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, + &sta->sta, tid, NULL, 0, false)) sdata_info(sta->sdata, "HW problem - can not stop rx aggregation for %pM tid %d\n", sta->sta.addr, tid); @@ -245,15 +237,6 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, { struct ieee80211_local *local = sta->sdata->local; struct tid_ampdu_rx *tid_agg_rx; - struct ieee80211_ampdu_params params = { - .sta = &sta->sta, - .action = IEEE80211_AMPDU_RX_START, - .tid = tid, - .amsdu = false, - .timeout = timeout, - .ssn = start_seq_num, - }; - int i, ret = -EOPNOTSUPP; u16 status = WLAN_STATUS_REQUEST_DECLINED; @@ -290,12 +273,8 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, buf_size = IEEE80211_MAX_AMPDU_BUF; /* make sure the size doesn't exceed the maximum supported by the hw */ - if (buf_size > sta->sta.max_rx_aggregation_subframes) - buf_size = sta->sta.max_rx_aggregation_subframes; - params.buf_size = buf_size; - - ht_dbg(sta->sdata, "AddBA Req buf_size=%d for %pM\n", - buf_size, sta->sta.addr); + if (buf_size > local->hw.max_rx_aggregation_subframes) + buf_size = local->hw.max_rx_aggregation_subframes; /* examine state machine */ mutex_lock(&sta->ampdu_mlme.mtx); @@ -343,7 +322,8 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, for (i = 0; i < buf_size; i++) __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); - ret = drv_ampdu_action(local, sta->sdata, ¶ms); + ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, + &sta->sta, tid, &start_seq_num, 0, false); ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", sta->sta.addr, tid, ret); if (ret) { diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 4932e9f243a2..ff757181b0a8 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -7,7 +7,6 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007, Michael Wu * Copyright 2007-2010, Intel Corporation - * Copyright(c) 2015 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -296,14 +295,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, { struct ieee80211_local *local = sta->local; struct tid_ampdu_tx *tid_tx; - struct ieee80211_ampdu_params params = { - .sta = &sta->sta, - .tid = tid, - .buf_size = 0, - .amsdu = false, - .timeout = 0, - .ssn = 0, - }; + enum ieee80211_ampdu_mlme_action action; int ret; lockdep_assert_held(&sta->ampdu_mlme.mtx); @@ -312,10 +304,10 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, case AGG_STOP_DECLINED: case AGG_STOP_LOCAL_REQUEST: case AGG_STOP_PEER_REQUEST: - params.action = IEEE80211_AMPDU_TX_STOP_CONT; + action = IEEE80211_AMPDU_TX_STOP_CONT; break; case AGG_STOP_DESTROY_STA: - params.action = IEEE80211_AMPDU_TX_STOP_FLUSH; + action = IEEE80211_AMPDU_TX_STOP_FLUSH; break; default: WARN_ON_ONCE(1); @@ -338,8 +330,9 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, spin_unlock_bh(&sta->lock); if (reason != AGG_STOP_DESTROY_STA) return -EALREADY; - params.action = IEEE80211_AMPDU_TX_STOP_FLUSH_CONT; - ret = drv_ampdu_action(local, sta->sdata, ¶ms); + ret = drv_ampdu_action(local, sta->sdata, + IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, + &sta->sta, tid, NULL, 0, false); WARN_ON_ONCE(ret); return 0; } @@ -388,7 +381,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, WLAN_BACK_INITIATOR; tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST; - ret = drv_ampdu_action(local, sta->sdata, ¶ms); + ret = drv_ampdu_action(local, sta->sdata, action, + &sta->sta, tid, NULL, 0, false); /* HW shall not deny going back to legacy */ if (WARN_ON(ret)) { @@ -451,14 +445,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) struct tid_ampdu_tx *tid_tx; struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; - struct ieee80211_ampdu_params params = { - .sta = &sta->sta, - .action = IEEE80211_AMPDU_TX_START, - .tid = tid, - .buf_size = 0, - .amsdu = false, - .timeout = 0, - }; + u16 start_seq_num; int ret; tid_tx = rcu_dereference_protected_tid_tx(sta, tid); @@ -480,8 +467,10 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) */ synchronize_net(); - params.ssn = sta->tid_seq[tid] >> 4; - ret = drv_ampdu_action(local, sdata, ¶ms); + start_seq_num = sta->tid_seq[tid] >> 4; + + ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, + &sta->sta, tid, &start_seq_num, 0, false); if (ret) { ht_dbg(sdata, "BA request denied - HW unavailable for %pM tid %d\n", @@ -510,7 +499,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) /* send AddBA request */ ieee80211_send_addba_request(sdata, sta->sta.addr, tid, - tid_tx->dialog_token, params.ssn, + tid_tx->dialog_token, start_seq_num, IEEE80211_MAX_AMPDU_BUF, tid_tx->timeout); } @@ -695,24 +684,18 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, struct sta_info *sta, u16 tid) { struct tid_ampdu_tx *tid_tx; - struct ieee80211_ampdu_params params = { - .sta = &sta->sta, - .action = IEEE80211_AMPDU_TX_OPERATIONAL, - .tid = tid, - .timeout = 0, - .ssn = 0, - }; lockdep_assert_held(&sta->ampdu_mlme.mtx); tid_tx = rcu_dereference_protected_tid_tx(sta, tid); - params.buf_size = tid_tx->buf_size; - params.amsdu = tid_tx->amsdu; ht_dbg(sta->sdata, "Aggregation is on for %pM tid %d\n", sta->sta.addr, tid); - drv_ampdu_action(local, sta->sdata, ¶ms); + drv_ampdu_action(local, sta->sdata, + IEEE80211_AMPDU_TX_OPERATIONAL, + &sta->sta, tid, NULL, tid_tx->buf_size, + tid_tx->amsdu); /* * synchronize with TX path, while splicing the TX path diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 00a8cc572a22..c12f348138ac 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -865,7 +865,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) /* free all potentially still buffered bcast frames */ local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); - ieee80211_purge_tx_queue(&local->hw, &sdata->u.ap.ps.bc_buf); + skb_queue_purge(&sdata->u.ap.ps.bc_buf); mutex_lock(&local->mtx); ieee80211_vif_copy_chanctx_to_vlans(sdata, true); @@ -2877,7 +2877,7 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) } if (beacon->probe_resp_len) { new_beacon->probe_resp_len = beacon->probe_resp_len; - new_beacon->probe_resp = pos; + beacon->probe_resp = pos; memcpy(pos, beacon->probe_resp, beacon->probe_resp_len); pos += beacon->probe_resp_len; } diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index e546a987a9d3..4d2aaebd4f97 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -91,7 +91,7 @@ static const struct file_operations reset_ops = { }; #endif -static const char *hw_flag_names[] = { +static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS + 1] = { #define FLAG(F) [IEEE80211_HW_##F] = #F FLAG(HAS_RATE_CONTROL), FLAG(RX_INCLUDES_FCS), @@ -125,6 +125,9 @@ static const char *hw_flag_names[] = { FLAG(TDLS_WIDER_BW), FLAG(SUPPORTS_AMSDU_IN_AMPDU), FLAG(BEACON_TX_STATUS), + + /* keep last for the build bug below */ + (void *)0x1 #undef FLAG }; @@ -144,7 +147,7 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, /* fail compilation if somebody adds or removes * a flag without updating the name array above */ - BUILD_BUG_ON(ARRAY_SIZE(hw_flag_names) != NUM_IEEE80211_HW_FLAGS); + BUILD_BUG_ON(hw_flag_names[NUM_IEEE80211_HW_FLAGS] != (void *)0x1); for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) { if (test_bit(i, local->hw.flags)) diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index c258f1041d33..ca1fe5576103 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -284,7 +284,9 @@ int drv_switch_vif_chanctx(struct ieee80211_local *local, int drv_ampdu_action(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - struct ieee80211_ampdu_params *params) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, + u16 *ssn, u8 buf_size, bool amsdu) { int ret = -EOPNOTSUPP; @@ -294,10 +296,12 @@ int drv_ampdu_action(struct ieee80211_local *local, if (!check_sdata_in_driver(sdata)) return -EIO; - trace_drv_ampdu_action(local, sdata, params); + trace_drv_ampdu_action(local, sdata, action, sta, tid, + ssn, buf_size, amsdu); if (local->ops->ampdu_action) - ret = local->ops->ampdu_action(&local->hw, &sdata->vif, params); + ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, + sta, tid, ssn, buf_size, amsdu); trace_drv_return_int(local, ret); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 18b0d65baff0..154ce4b13406 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -585,7 +585,9 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) int drv_ampdu_action(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - struct ieee80211_ampdu_params *params); + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, + u16 *ssn, u8 buf_size, bool amsdu); static inline int drv_get_survey(struct ieee80211_local *local, int idx, struct survey_info *survey) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 24ba31601fc9..980e9e9b6684 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -66,8 +66,6 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, 2 + (IEEE80211_MAX_SUPP_RATES - 8) + 2 + sizeof(struct ieee80211_ht_cap) + 2 + sizeof(struct ieee80211_ht_operation) + - 2 + sizeof(struct ieee80211_vht_cap) + - 2 + sizeof(struct ieee80211_vht_operation) + ifibss->ie_len; presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL); if (!presp) @@ -488,14 +486,14 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, struct beacon_data *presp, *old_presp; struct cfg80211_bss *cbss; const struct cfg80211_bss_ies *ies; - u16 capability = WLAN_CAPABILITY_IBSS; + u16 capability = 0; u64 tsf; int ret = 0; sdata_assert_lock(sdata); if (ifibss->privacy) - capability |= WLAN_CAPABILITY_PRIVACY; + capability = WLAN_CAPABILITY_PRIVACY; cbss = cfg80211_get_bss(sdata->local->hw.wiphy, ifibss->chandef.chan, ifibss->bssid, ifibss->ssid, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 7b271f3ded6b..6837a46ca4a2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -682,6 +682,7 @@ struct ieee80211_if_mesh { const struct ieee80211_mesh_sync_ops *sync_ops; s64 sync_offset_clockdrift_max; spinlock_t sync_offset_lock; + bool adjusting_tbtt; /* mesh power save */ enum nl80211_mesh_power_mode nonpeer_pm; int ps_peers_light_sleep; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 58588a610b05..bcb0a1b64556 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1441,7 +1441,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, break; case NL80211_IFTYPE_UNSPECIFIED: case NUM_NL80211_IFTYPES: - WARN_ON(1); + BUG(); break; } diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 4a72c0d1e56f..44388d6a1d8e 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -4,7 +4,6 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007-2008 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH - * Copyright 2017 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -19,7 +18,6 @@ #include #include #include -#include #include #include "ieee80211_i.h" #include "driver-ops.h" @@ -608,39 +606,6 @@ void ieee80211_key_free_unused(struct ieee80211_key *key) ieee80211_key_free_common(key); } -static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata, - struct ieee80211_key *old, - struct ieee80211_key *new) -{ - u8 tkip_old[WLAN_KEY_LEN_TKIP], tkip_new[WLAN_KEY_LEN_TKIP]; - u8 *tk_old, *tk_new; - - if (!old || new->conf.keylen != old->conf.keylen) - return false; - - tk_old = old->conf.key; - tk_new = new->conf.key; - - /* - * In station mode, don't compare the TX MIC key, as it's never used - * and offloaded rekeying may not care to send it to the host. This - * is the case in iwlwifi, for example. - */ - if (sdata->vif.type == NL80211_IFTYPE_STATION && - new->conf.cipher == WLAN_CIPHER_SUITE_TKIP && - new->conf.keylen == WLAN_KEY_LEN_TKIP && - !(new->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) { - memcpy(tkip_old, tk_old, WLAN_KEY_LEN_TKIP); - memcpy(tkip_new, tk_new, WLAN_KEY_LEN_TKIP); - memset(tkip_old + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8); - memset(tkip_new + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8); - tk_old = tkip_old; - tk_new = tkip_new; - } - - return !crypto_memneq(tk_old, tk_new, new->conf.keylen); -} - int ieee80211_key_link(struct ieee80211_key *key, struct ieee80211_sub_if_data *sdata, struct sta_info *sta) @@ -652,6 +617,9 @@ int ieee80211_key_link(struct ieee80211_key *key, pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; idx = key->conf.keyidx; + key->local = sdata->local; + key->sdata = sdata; + key->sta = sta; mutex_lock(&sdata->local->key_mtx); @@ -662,20 +630,6 @@ int ieee80211_key_link(struct ieee80211_key *key, else old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]); - /* - * Silently accept key re-installation without really installing the - * new version of the key to avoid nonce reuse or replay issues. - */ - if (ieee80211_key_identical(sdata, old_key, key)) { - ieee80211_key_free_unused(key); - ret = 0; - goto out; - } - - key->local = sdata->local; - key->sdata = sdata; - key->sta = sta; - increment_tailroom_need_count(sdata); ieee80211_key_replace(sdata, sta, pairwise, old_key, key); @@ -691,7 +645,6 @@ int ieee80211_key_link(struct ieee80211_key *key, ret = 0; } - out: mutex_unlock(&sdata->local->key_mtx); return ret; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 2ee53dc1ddf7..175ffcf7fb06 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -891,17 +891,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) supp_ht = supp_ht || sband->ht_cap.ht_supported; supp_vht = supp_vht || sband->vht_cap.vht_supported; - if (!sband->ht_cap.ht_supported) - continue; + if (sband->ht_cap.ht_supported) + local->rx_chains = + max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs), + local->rx_chains); /* TODO: consider VHT for RX chains, hopefully it's the same */ - local->rx_chains = - max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs), - local->rx_chains); - - /* no need to mask, SM_PS_DISABLED has all bits set */ - sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED << - IEEE80211_HT_CAP_SM_PS_SHIFT; } /* if low-level driver supports AP, we also support VLAN */ diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 1cbc7bd26de3..6f85b6ab8e51 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -151,26 +151,19 @@ u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) void mesh_sta_cleanup(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; - u32 changed = 0; + u32 changed; /* * maybe userspace handles peer allocation and peering, but in either * case the beacon is still generated by the kernel and we might need * an update. */ - if (sdata->u.mesh.user_mpm && - sta->mesh->plink_state == NL80211_PLINK_ESTAB) - changed |= mesh_plink_dec_estab_count(sdata); - changed |= mesh_accept_plinks_update(sdata); + changed = mesh_accept_plinks_update(sdata); if (!sdata->u.mesh.user_mpm) { changed |= mesh_plink_deactivate(sta); del_timer_sync(&sta->mesh->plink_timer); } - /* make sure no readers can access nexthop sta from here on */ - mesh_path_flush_by_nexthop(sta); - synchronize_net(); - if (changed) ieee80211_mbss_info_change_notify(sdata, changed); } @@ -295,6 +288,10 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ *pos |= ifmsh->ps_peers_deep_sleep ? IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00; + *pos++ |= ifmsh->adjusting_tbtt ? + IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; + *pos++ = 0x00; + return 0; } @@ -351,7 +348,7 @@ int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata, /* fast-forward to vendor IEs */ offset = ieee80211_ie_split_vendor(ifmsh->ie, ifmsh->ie_len, 0); - if (offset < ifmsh->ie_len) { + if (offset) { len = ifmsh->ie_len - offset; data = ifmsh->ie + offset; if (skb_tailroom(skb) < len) @@ -862,6 +859,7 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ifmsh->mesh_cc_id = 0; /* Disabled */ /* register sync ops from extensible synchronization framework */ ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id); + ifmsh->adjusting_tbtt = false; ifmsh->sync_offset_clockdrift_max = 0; set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); ieee80211_mesh_root_setup(ifmsh); diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index f55cddcd556c..b6dc2d7cd650 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -776,7 +776,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, struct mesh_path *mpath; u8 ttl, flags, hopcount; const u8 *orig_addr; - u32 orig_sn, new_metric, orig_metric, last_hop_metric, interval; + u32 orig_sn, metric, metric_txsta, interval; bool root_is_gate; ttl = rann->rann_ttl; @@ -787,7 +787,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, interval = le32_to_cpu(rann->rann_interval); hopcount = rann->rann_hopcount; hopcount++; - orig_metric = le32_to_cpu(rann->rann_metric); + metric = le32_to_cpu(rann->rann_metric); /* Ignore our own RANNs */ if (ether_addr_equal(orig_addr, sdata->vif.addr)) @@ -804,10 +804,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, return; } - last_hop_metric = airtime_link_metric_get(local, sta); - new_metric = orig_metric + last_hop_metric; - if (new_metric < orig_metric) - new_metric = MAX_METRIC; + metric_txsta = airtime_link_metric_get(local, sta); mpath = mesh_path_lookup(sdata, orig_addr); if (!mpath) { @@ -820,7 +817,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, } if (!(SN_LT(mpath->sn, orig_sn)) && - !(mpath->sn == orig_sn && new_metric < mpath->rann_metric)) { + !(mpath->sn == orig_sn && metric < mpath->rann_metric)) { rcu_read_unlock(); return; } @@ -838,7 +835,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, } mpath->sn = orig_sn; - mpath->rann_metric = new_metric; + mpath->rann_metric = metric + metric_txsta; mpath->is_root = true; /* Recording RANNs sender address to send individually * addressed PREQs destined for root mesh STA */ @@ -858,7 +855,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, orig_sn, 0, NULL, 0, broadcast_addr, hopcount, ttl, interval, - new_metric, 0, sdata); + metric + metric_txsta, 0, sdata); } rcu_read_unlock(); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 9f02e54ad2a5..bd3d55eb21d4 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -495,14 +495,12 @@ mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr, /* Userspace handles station allocation */ if (sdata->u.mesh.user_mpm || - sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) { - if (mesh_peer_accepts_plinks(elems) && - mesh_plink_availables(sdata)) - cfg80211_notify_new_peer_candidate(sdata->dev, addr, - elems->ie_start, - elems->total_len, - GFP_KERNEL); - } else + sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) + cfg80211_notify_new_peer_candidate(sdata->dev, addr, + elems->ie_start, + elems->total_len, + GFP_KERNEL); + else sta = __mesh_sta_info_alloc(sdata, addr); return sta; diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index 16ed43fe4841..64bc22ad9496 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c @@ -119,6 +119,7 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, */ if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) { + clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); msync_dbg(sdata, "STA %pM : is adjusting TBTT\n", sta->sta.addr); goto no_sync; @@ -167,9 +168,11 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata, struct beacon_data *beacon) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + u8 cap; WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); WARN_ON(!rcu_read_lock_held()); + cap = beacon->meshconf->meshconf_cap; spin_lock_bh(&ifmsh->sync_offset_lock); @@ -183,13 +186,21 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata, "TBTT : kicking off TBTT adjustment with clockdrift_max=%lld\n", ifmsh->sync_offset_clockdrift_max); set_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags); + + ifmsh->adjusting_tbtt = true; } else { msync_dbg(sdata, "TBTT : max clockdrift=%lld; too small to adjust\n", (long long)ifmsh->sync_offset_clockdrift_max); ifmsh->sync_offset_clockdrift_max = 0; + + ifmsh->adjusting_tbtt = false; } spin_unlock_bh(&ifmsh->sync_offset_lock); + + beacon->meshconf->meshconf_cap = ifmsh->adjusting_tbtt ? + IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING | cap : + ~IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING & cap; } static const struct sync_method sync_methods[] = { diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 005cd8796505..83097c3832d1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2517,7 +2517,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, } static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, - bool assoc, bool abandon) + bool assoc) { struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; @@ -2539,9 +2539,6 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, mutex_lock(&sdata->local->mtx); ieee80211_vif_release_channel(sdata); mutex_unlock(&sdata->local->mtx); - - if (abandon) - cfg80211_abandon_assoc(sdata->dev, assoc_data->bss); } kfree(assoc_data); @@ -2771,7 +2768,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, bssid, reason_code, ieee80211_get_reason_code_string(reason_code)); - ieee80211_destroy_assoc_data(sdata, false, true); + ieee80211_destroy_assoc_data(sdata, false); cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); return; @@ -3176,14 +3173,14 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (status_code != WLAN_STATUS_SUCCESS) { sdata_info(sdata, "%pM denied association (code=%d)\n", mgmt->sa, status_code); - ieee80211_destroy_assoc_data(sdata, false, false); + ieee80211_destroy_assoc_data(sdata, false); event.u.mlme.status = MLME_DENIED; event.u.mlme.reason = status_code; drv_event_callback(sdata->local, sdata, &event); } else { if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) { /* oops -- internal error -- send timeout for now */ - ieee80211_destroy_assoc_data(sdata, false, false); + ieee80211_destroy_assoc_data(sdata, false); cfg80211_assoc_timeout(sdata->dev, bss); return; } @@ -3196,7 +3193,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, * recalc after assoc_data is NULL but before associated * is set can cause the interface to go idle */ - ieee80211_destroy_assoc_data(sdata, true, false); + ieee80211_destroy_assoc_data(sdata, true); /* get uapsd queues configuration */ uapsd_queues = 0; @@ -3891,7 +3888,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) .u.mlme.status = MLME_TIMEOUT, }; - ieee80211_destroy_assoc_data(sdata, false, false); + ieee80211_destroy_assoc_data(sdata, false); cfg80211_assoc_timeout(sdata->dev, bss); drv_event_callback(sdata->local, sdata, &event); } @@ -4032,7 +4029,7 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata) WLAN_REASON_DEAUTH_LEAVING, false, frame_buf); if (ifmgd->assoc_data) - ieee80211_destroy_assoc_data(sdata, false, true); + ieee80211_destroy_assoc_data(sdata, false); if (ifmgd->auth_data) ieee80211_destroy_auth_data(sdata, false); cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, @@ -4326,10 +4323,6 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) return -EINVAL; - /* If a reconfig is happening, bail out */ - if (local->in_reconfig) - return -EBUSY; - if (assoc) { rcu_read_lock(); have_sta = sta_info_get(sdata, cbss->bssid); @@ -4912,7 +4905,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, IEEE80211_STYPE_DEAUTH, req->reason_code, tx, frame_buf); - ieee80211_destroy_assoc_data(sdata, false, true); + ieee80211_destroy_assoc_data(sdata, false); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, req->reason_code); @@ -4987,7 +4980,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) sdata_lock(sdata); if (ifmgd->assoc_data) { struct cfg80211_bss *bss = ifmgd->assoc_data->bss; - ieee80211_destroy_assoc_data(sdata, false, false); + ieee80211_destroy_assoc_data(sdata, false); cfg80211_assoc_timeout(sdata->dev, bss); } if (ifmgd->auth_data) diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index b6be51940ead..04401037140e 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -469,8 +469,6 @@ void ieee80211_roc_purge(struct ieee80211_local *local, struct ieee80211_roc_work *roc, *tmp; LIST_HEAD(tmp_list); - flush_work(&local->hw_roc_start); - mutex_lock(&local->mtx); list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { if (sdata && roc->sdata != sdata) diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 0402fa45b343..00a43a70e1fc 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -168,7 +168,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) break; } - flush_delayed_work(&sdata->dec_tailroom_needed_wk); drv_remove_interface(local, sdata); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f8406c37fc1d..a3bb8f7f5fc5 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1455,16 +1455,12 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) */ if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) && !ieee80211_has_morefrags(hdr->frame_control) && - !ieee80211_is_back_req(hdr->frame_control) && !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && (rx->sdata->vif.type == NL80211_IFTYPE_AP || rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && - /* - * PM bit is only checked in frames where it isn't reserved, + /* PM bit is only checked in frames where it isn't reserved, * in AP mode it's reserved in non-bufferable management frames * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) - * BAR frames should be ignored as specified in - * IEEE 802.11-2012 10.2.1.2. */ (!ieee80211_is_mgmt(hdr->frame_control) || ieee80211_is_bufferable_mmpdu(hdr->frame_control))) { @@ -2207,22 +2203,16 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) if (!(status->rx_flags & IEEE80211_RX_AMSDU)) return RX_CONTINUE; - if (unlikely(ieee80211_has_a4(hdr->frame_control))) { - switch (rx->sdata->vif.type) { - case NL80211_IFTYPE_AP_VLAN: - if (!rx->sdata->u.vlan.sta) - return RX_DROP_UNUSABLE; - break; - case NL80211_IFTYPE_STATION: - if (!rx->sdata->u.mgd.use_4addr) - return RX_DROP_UNUSABLE; - break; - default: - return RX_DROP_UNUSABLE; - } - } + if (ieee80211_has_a4(hdr->frame_control) && + rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + !rx->sdata->u.vlan.sta) + return RX_DROP_UNUSABLE; - if (is_multicast_ether_addr(hdr->addr1)) + if (is_multicast_ether_addr(hdr->addr1) && + ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + rx->sdata->u.vlan.sta) || + (rx->sdata->vif.type == NL80211_IFTYPE_STATION && + rx->sdata->u.mgd.use_4addr))) return RX_DROP_UNUSABLE; skb->dev = dev; @@ -3367,8 +3357,6 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx) } return true; case NL80211_IFTYPE_MESH_POINT: - if (ether_addr_equal(sdata->vif.addr, hdr->addr2)) - return false; if (multicast) return true; return ether_addr_equal(sdata->vif.addr, hdr->addr1); @@ -3402,27 +3390,6 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx) !ether_addr_equal(bssid, hdr->addr1)) return false; } - - /* - * 802.11-2016 Table 9-26 says that for data frames, A1 must be - * the BSSID - we've checked that already but may have accepted - * the wildcard (ff:ff:ff:ff:ff:ff). - * - * It also says: - * The BSSID of the Data frame is determined as follows: - * a) If the STA is contained within an AP or is associated - * with an AP, the BSSID is the address currently in use - * by the STA contained in the AP. - * - * So we should not accept data frames with an address that's - * multicast. - * - * Accepting it also opens a security problem because stations - * could encrypt it with the GTK and inject traffic that way. - */ - if (ieee80211_is_data(hdr->frame_control) && multicast) - return false; - return true; case NL80211_IFTYPE_WDS: if (bssid || !ieee80211_is_data(hdr->frame_control)) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 7e7b9ef29d8d..67066d048e6f 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -329,9 +329,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, memcpy(sta->addr, addr, ETH_ALEN); memcpy(sta->sta.addr, addr, ETH_ALEN); - sta->sta.max_rx_aggregation_subframes = - local->hw.max_rx_aggregation_subframes; - sta->local = local; sta->sdata = sdata; sta->rx_stats.last_rx = jiffies; @@ -661,7 +658,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending) } /* No need to do anything if the driver does all */ - if (ieee80211_hw_check(&local->hw, AP_LINK_PS) && !local->ops->set_tim) + if (ieee80211_hw_check(&local->hw, AP_LINK_PS)) return; if (sta->dead) diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 15b0150283b6..2cafb21b422f 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -269,7 +269,7 @@ struct ieee80211_fast_tx { u8 sa_offs, da_offs, pn_offs; u8 band; u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV + - sizeof(rfc1042_header)] __aligned(2); + sizeof(rfc1042_header)]; struct rcu_head rcu_head; }; diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 45fb1abdb265..5bad05e9af90 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -194,7 +194,6 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) } if (ieee80211_is_action(mgmt->frame_control) && - !ieee80211_has_protected(mgmt->frame_control) && mgmt->u.action.category == WLAN_CATEGORY_HT && mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS && ieee80211_sdata_running(sdata)) { diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 913e959b03cf..56c6d6cfa5a1 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -80,23 +80,7 @@ #define KEY_PR_FMT " cipher:0x%x, flags=%#x, keyidx=%d, hw_key_idx=%d" #define KEY_PR_ARG __entry->cipher, __entry->flags, __entry->keyidx, __entry->hw_key_idx -#define AMPDU_ACTION_ENTRY __field(enum ieee80211_ampdu_mlme_action, \ - ieee80211_ampdu_mlme_action) \ - STA_ENTRY \ - __field(u16, tid) \ - __field(u16, ssn) \ - __field(u8, buf_size) \ - __field(bool, amsdu) \ - __field(u16, timeout) -#define AMPDU_ACTION_ASSIGN STA_NAMED_ASSIGN(params->sta); \ - __entry->tid = params->tid; \ - __entry->ssn = params->ssn; \ - __entry->buf_size = params->buf_size; \ - __entry->amsdu = params->amsdu; \ - __entry->timeout = params->timeout; -#define AMPDU_ACTION_PR_FMT STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d" -#define AMPDU_ACTION_PR_ARG STA_PR_ARG, __entry->tid, __entry->ssn, \ - __entry->buf_size, __entry->amsdu, __entry->timeout + /* * Tracing for driver callbacks. @@ -986,25 +970,38 @@ DEFINE_EVENT(local_only_evt, drv_tx_last_beacon, TRACE_EVENT(drv_ampdu_action, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - struct ieee80211_ampdu_params *params), + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, + u16 *ssn, u8 buf_size, bool amsdu), - TP_ARGS(local, sdata, params), + TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size, amsdu), TP_STRUCT__entry( LOCAL_ENTRY + STA_ENTRY + __field(u32, action) + __field(u16, tid) + __field(u16, ssn) + __field(u8, buf_size) + __field(bool, amsdu) VIF_ENTRY - AMPDU_ACTION_ENTRY ), TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - AMPDU_ACTION_ASSIGN; + STA_ASSIGN; + __entry->action = action; + __entry->tid = tid; + __entry->ssn = ssn ? *ssn : 0; + __entry->buf_size = buf_size; + __entry->amsdu = amsdu; ), TP_printk( - LOCAL_PR_FMT VIF_PR_FMT AMPDU_ACTION_PR_FMT, - LOCAL_PR_ARG, VIF_PR_ARG, AMPDU_ACTION_PR_ARG + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d amsdu:%d", + LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, + __entry->tid, __entry->buf_size, __entry->amsdu ) ); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ea5dfefd765a..bdc224d5053a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -365,7 +365,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) skb = skb_dequeue(&ps->bc_buf); if (skb) { purged++; - ieee80211_free_txskb(&local->hw, skb); + dev_kfree_skb(skb); } total += skb_queue_len(&ps->bc_buf); } @@ -448,7 +448,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) if (skb_queue_len(&ps->bc_buf) >= AP_MAX_BC_BUFFER) { ps_dbg(tx->sdata, "BC TX buffer full - dropping the oldest frame\n"); - ieee80211_free_txskb(&tx->local->hw, skb_dequeue(&ps->bc_buf)); + dev_kfree_skb(skb_dequeue(&ps->bc_buf)); } else tx->local->total_ps_buffered++; @@ -2699,7 +2699,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2); int hw_headroom = sdata->local->hw.extra_tx_headroom; struct ethhdr eth; - struct ieee80211_tx_info *info; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (void *)fast_tx->hdr; struct ieee80211_tx_data tx; ieee80211_tx_result r; @@ -2761,7 +2761,6 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN); memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN); - info = IEEE80211_SKB_CB(skb); memset(info, 0, sizeof(*info)); info->band = fast_tx->band; info->control.vif = &sdata->vif; @@ -3782,7 +3781,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb)) break; - ieee80211_free_txskb(hw, skb); + dev_kfree_skb_any(skb); } info = IEEE80211_SKB_CB(skb); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 2214c77d4172..33344f5a66a8 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -2006,8 +2006,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) if (!sta->uploaded) continue; - if (sta->sdata->vif.type != NL80211_IFTYPE_AP && - sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN) + if (sta->sdata->vif.type != NL80211_IFTYPE_AP) continue; for (state = IEEE80211_STA_NOTEXIST; @@ -2664,9 +2663,8 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, rate = cfg80211_calculate_bitrate(&ri); if (WARN_ONCE(!rate, - "Invalid bitrate: flags=0x%llx, idx=%d, vht_nss=%d\n", - (unsigned long long)status->flag, status->rate_idx, - status->vht_nss)) + "Invalid bitrate: flags=0x%x, idx=%d, vht_nss=%d\n", + status->flag, status->rate_idx, status->vht_nss)) return 0; /* rewind from end of MPDU */ diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 73e8f347802e..efa3f48f1ec5 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -293,8 +293,7 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) return RX_DROP_UNUSABLE; ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); /* remove ICV */ - if (!(status->flag & RX_FLAG_ICV_STRIPPED) && - pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN)) + if (pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN)) return RX_DROP_UNUSABLE; } diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index cb439e06919f..d824c38971ed 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -16,7 +16,6 @@ #include #include #include -#include #include "ieee80211_i.h" #include "michael.h" @@ -153,7 +152,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; michael_mic(key, hdr, data, data_len, mic); - if (crypto_memneq(mic, data + data_len, MICHAEL_MIC_LEN)) + if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) goto mic_fail; /* remove Michael MIC from payload */ @@ -298,8 +297,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) return RX_DROP_UNUSABLE; /* Trim ICV */ - if (!(status->flag & RX_FLAG_ICV_STRIPPED)) - skb_trim(skb, skb->len - IEEE80211_TKIP_ICV_LEN); + skb_trim(skb, skb->len - IEEE80211_TKIP_ICV_LEN); /* Remove IV */ memmove(skb->data + IEEE80211_TKIP_IV_LEN, skb->data, hdrlen); @@ -509,31 +507,25 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, !ieee80211_is_robust_mgmt_frame(skb)) return RX_CONTINUE; + data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len; + if (!rx->sta || data_len < 0) + return RX_DROP_UNUSABLE; + if (status->flag & RX_FLAG_DECRYPTED) { if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_CCMP_HDR_LEN)) return RX_DROP_UNUSABLE; - if (status->flag & RX_FLAG_MIC_STRIPPED) - mic_len = 0; } else { if (skb_linearize(rx->skb)) return RX_DROP_UNUSABLE; } - data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len; - if (!rx->sta || data_len < 0) - return RX_DROP_UNUSABLE; - if (!(status->flag & RX_FLAG_PN_VALIDATED)) { - int res; - ccmp_hdr2pn(pn, skb->data + hdrlen); queue = rx->security_idx; - res = memcmp(pn, key->u.ccmp.rx_pn[queue], - IEEE80211_CCMP_PN_LEN); - if (res < 0 || - (!res && !(status->flag & RX_FLAG_ALLOW_SAME_PN))) { + if (memcmp(pn, key->u.ccmp.rx_pn[queue], + IEEE80211_CCMP_PN_LEN) <= 0) { key->u.ccmp.replays++; return RX_DROP_UNUSABLE; } @@ -731,7 +723,8 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) struct sk_buff *skb = rx->skb; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); u8 pn[IEEE80211_GCMP_PN_LEN]; - int data_len, queue, mic_len = IEEE80211_GCMP_MIC_LEN; + int data_len; + int queue; hdrlen = ieee80211_hdrlen(hdr->frame_control); @@ -739,31 +732,26 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) !ieee80211_is_robust_mgmt_frame(skb)) return RX_CONTINUE; + data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - + IEEE80211_GCMP_MIC_LEN; + if (!rx->sta || data_len < 0) + return RX_DROP_UNUSABLE; + if (status->flag & RX_FLAG_DECRYPTED) { if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_GCMP_HDR_LEN)) return RX_DROP_UNUSABLE; - if (status->flag & RX_FLAG_MIC_STRIPPED) - mic_len = 0; } else { if (skb_linearize(rx->skb)) return RX_DROP_UNUSABLE; } - data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - mic_len; - if (!rx->sta || data_len < 0) - return RX_DROP_UNUSABLE; - if (!(status->flag & RX_FLAG_PN_VALIDATED)) { - int res; - gcmp_hdr2pn(pn, skb->data + hdrlen); queue = rx->security_idx; - res = memcmp(pn, key->u.gcmp.rx_pn[queue], - IEEE80211_GCMP_PN_LEN); - if (res < 0 || - (!res && !(status->flag & RX_FLAG_ALLOW_SAME_PN))) { + if (memcmp(pn, key->u.gcmp.rx_pn[queue], + IEEE80211_GCMP_PN_LEN) <= 0) { key->u.gcmp.replays++; return RX_DROP_UNUSABLE; } @@ -787,7 +775,7 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) } /* Remove GCMP header and MIC */ - if (pskb_trim(skb, skb->len - mic_len)) + if (pskb_trim(skb, skb->len - IEEE80211_GCMP_MIC_LEN)) return RX_DROP_UNUSABLE; memmove(skb->data + IEEE80211_GCMP_HDR_LEN, skb->data, hdrlen); skb_pull(skb, IEEE80211_GCMP_HDR_LEN); @@ -1056,7 +1044,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) bip_aad(skb, aad); ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, skb->data + 24, skb->len - 24, mic); - if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { + if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { key->u.aes_cmac.icverrors++; return RX_DROP_UNUSABLE; } @@ -1106,7 +1094,7 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx) bip_aad(skb, aad); ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad, skb->data + 24, skb->len - 24, mic); - if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { + if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { key->u.aes_cmac.icverrors++; return RX_DROP_UNUSABLE; } @@ -1210,7 +1198,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx) if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce, skb->data + 24, skb->len - 24, mic) < 0 || - crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { + memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { key->u.aes_gmac.icverrors++; return RX_DROP_UNUSABLE; } diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index c2ce7dec5198..881bc2072809 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -715,22 +714,6 @@ static int mpls_nh_build_multi(struct mpls_route_config *cfg, return err; } -static bool mpls_label_ok(struct net *net, unsigned int *index) -{ - bool is_ok = true; - - /* Reserved labels may not be set */ - if (*index < MPLS_LABEL_FIRST_UNRESERVED) - is_ok = false; - - /* The full 20 bit range may not be supported. */ - if (is_ok && *index >= net->mpls.platform_labels) - is_ok = false; - - *index = array_index_nospec(*index, net->mpls.platform_labels); - return is_ok; -} - static int mpls_route_add(struct mpls_route_config *cfg) { struct mpls_route __rcu **platform_label; @@ -749,7 +732,12 @@ static int mpls_route_add(struct mpls_route_config *cfg) index = find_free_label(net); } - if (!mpls_label_ok(net, &index)) + /* Reserved labels may not be set */ + if (index < MPLS_LABEL_FIRST_UNRESERVED) + goto errout; + + /* The full 20 bit range may not be supported. */ + if (index >= net->mpls.platform_labels) goto errout; /* Append makes no sense with mpls */ @@ -810,7 +798,12 @@ static int mpls_route_del(struct mpls_route_config *cfg) index = cfg->rc_label; - if (!mpls_label_ok(net, &index)) + /* Reserved labels may not be removed */ + if (index < MPLS_LABEL_FIRST_UNRESERVED) + goto errout; + + /* The full 20 bit range may not be supported */ + if (index >= net->mpls.platform_labels) goto errout; mpls_route_update(net, index, NULL, &cfg->rc_nlinfo); @@ -1169,9 +1162,10 @@ static int rtm_to_route_config(struct sk_buff *skb, struct nlmsghdr *nlh, &cfg->rc_label)) goto errout; - if (!mpls_label_ok(cfg->rc_nlinfo.nl_net, - &cfg->rc_label)) + /* Reserved labels may not be set */ + if (cfg->rc_label < MPLS_LABEL_FIRST_UNRESERVED) goto errout; + break; } case RTA_VIA: @@ -1573,7 +1567,6 @@ static void mpls_net_exit(struct net *net) for (index = 0; index < platform_labels; index++) { struct mpls_route *rt = rtnl_dereference(platform_label[index]); RCU_INIT_POINTER(platform_label[index], NULL); - mpls_notify_route(net, index, rt, NULL, NULL); mpls_rt_free(rt); } rtnl_unlock(); diff --git a/net/mptcp/mptcp_input.c b/net/mptcp/mptcp_input.c index 9c6fcc4eeef4..4f691da044b5 100644 --- a/net/mptcp/mptcp_input.c +++ b/net/mptcp/mptcp_input.c @@ -952,7 +952,7 @@ static int mptcp_queue_skb(struct sock *sk) tp->mptcp->map_subseq + tp->mptcp->map_data_len)) break; } - tcp_enter_quickack_mode(sk, 1); + tcp_enter_quickack_mode(sk); } else { /* Ready for the meta-rcv-queue */ skb_queue_walk_safe(&sk->sk_receive_queue, tmp1, tmp) { diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index 299edc6add5a..0328f7250693 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c @@ -605,13 +605,17 @@ static const struct file_operations ip_vs_app_fops = { int __net_init ip_vs_app_net_init(struct netns_ipvs *ipvs) { + struct net *net = ipvs->net; + INIT_LIST_HEAD(&ipvs->app_list); - proc_create("ip_vs_app", 0, ipvs->net->proc_net, &ip_vs_app_fops); + proc_create("ip_vs_app", 0, net->proc_net, &ip_vs_app_fops); return 0; } void __net_exit ip_vs_app_net_cleanup(struct netns_ipvs *ipvs) { + struct net *net = ipvs->net; + unregister_ip_vs_app(ipvs, NULL /* all */); - remove_proc_entry("ip_vs_app", ipvs->net->proc_net); + remove_proc_entry("ip_vs_app", net->proc_net); } diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index dd1649caa2b2..4da560005b0e 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -845,8 +845,10 @@ static int handle_response_icmp(int af, struct sk_buff *skb, { unsigned int verdict = NF_DROP; - if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) - goto ignore_cp; + if (IP_VS_FWD_METHOD(cp) != 0) { + pr_err("shouldn't reach here, because the box is on the " + "half connection in the tun/dr module.\n"); + } /* Ensure the checksum is correct */ if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) { @@ -880,8 +882,6 @@ static int handle_response_icmp(int af, struct sk_buff *skb, ip_vs_notrack(skb); else ip_vs_update_conntrack(skb, cp, 0); - -ignore_cp: verdict = NF_ACCEPT; out: @@ -1242,11 +1242,8 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in */ cp = pp->conn_out_get(ipvs, af, skb, &iph); - if (likely(cp)) { - if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) - goto ignore_cp; + if (likely(cp)) return handle_response(af, skb, pd, cp, &iph, hooknum); - } if (sysctl_nat_icmp_send(ipvs) && (pp->protocol == IPPROTO_TCP || pp->protocol == IPPROTO_UDP || @@ -1288,15 +1285,9 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in } } } - -out: IP_VS_DBG_PKT(12, af, pp, skb, iph.off, "ip_vs_out: packet continues traversal as normal"); return NF_ACCEPT; - -ignore_cp: - __ip_vs_conn_put(cp); - goto out; } /* diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 3167ec76903a..e7c1b052c2a3 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1999,16 +1999,12 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v) seq_puts(seq, " -> RemoteAddress:Port Forward Weight ActiveConn InActConn\n"); } else { - struct net *net = seq_file_net(seq); - struct netns_ipvs *ipvs = net_ipvs(net); const struct ip_vs_service *svc = v; const struct ip_vs_iter *iter = seq->private; const struct ip_vs_dest *dest; struct ip_vs_scheduler *sched = rcu_dereference(svc->scheduler); char *sched_name = sched ? sched->name : "none"; - if (svc->ipvs != ipvs) - return 0; if (iter->table == ip_vs_svc_table) { #ifdef CONFIG_IP_VS_IPV6 if (svc->af == AF_INET6) @@ -2349,12 +2345,14 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) struct ipvs_sync_daemon_cfg cfg; memset(&cfg, 0, sizeof(cfg)); - ret = -EINVAL; - if (strscpy(cfg.mcast_ifn, dm->mcast_ifn, - sizeof(cfg.mcast_ifn)) <= 0) - goto out_dec; + strlcpy(cfg.mcast_ifn, dm->mcast_ifn, + sizeof(cfg.mcast_ifn)); cfg.syncid = dm->syncid; + rtnl_lock(); + mutex_lock(&ipvs->sync_mutex); ret = start_sync_thread(ipvs, &cfg, dm->state); + mutex_unlock(&ipvs->sync_mutex); + rtnl_unlock(); } else { mutex_lock(&ipvs->sync_mutex); ret = stop_sync_thread(ipvs, dm->state); @@ -2390,19 +2388,12 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) } } - if ((cmd == IP_VS_SO_SET_ADD || cmd == IP_VS_SO_SET_EDIT) && - strnlen(usvc.sched_name, IP_VS_SCHEDNAME_MAXLEN) == - IP_VS_SCHEDNAME_MAXLEN) { - ret = -EINVAL; - goto out_unlock; - } - /* Check for valid protocol: TCP or UDP or SCTP, even for fwmark!=0 */ if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP && usvc.protocol != IPPROTO_SCTP) { - pr_err("set_ctl: invalid protocol: %d %pI4:%d\n", + pr_err("set_ctl: invalid protocol: %d %pI4:%d %s\n", usvc.protocol, &usvc.addr.ip, - ntohs(usvc.port)); + ntohs(usvc.port), usvc.sched_name); ret = -EFAULT; goto out_unlock; } @@ -2831,7 +2822,7 @@ static const struct nla_policy ip_vs_cmd_policy[IPVS_CMD_ATTR_MAX + 1] = { static const struct nla_policy ip_vs_daemon_policy[IPVS_DAEMON_ATTR_MAX + 1] = { [IPVS_DAEMON_ATTR_STATE] = { .type = NLA_U32 }, [IPVS_DAEMON_ATTR_MCAST_IFN] = { .type = NLA_NUL_STRING, - .len = IP_VS_IFNAME_MAXLEN - 1 }, + .len = IP_VS_IFNAME_MAXLEN }, [IPVS_DAEMON_ATTR_SYNC_ID] = { .type = NLA_U32 }, [IPVS_DAEMON_ATTR_SYNC_MAXLEN] = { .type = NLA_U16 }, [IPVS_DAEMON_ATTR_MCAST_GROUP] = { .type = NLA_U32 }, @@ -2849,7 +2840,7 @@ static const struct nla_policy ip_vs_svc_policy[IPVS_SVC_ATTR_MAX + 1] = { [IPVS_SVC_ATTR_PORT] = { .type = NLA_U16 }, [IPVS_SVC_ATTR_FWMARK] = { .type = NLA_U32 }, [IPVS_SVC_ATTR_SCHED_NAME] = { .type = NLA_NUL_STRING, - .len = IP_VS_SCHEDNAME_MAXLEN - 1 }, + .len = IP_VS_SCHEDNAME_MAXLEN }, [IPVS_SVC_ATTR_PE_NAME] = { .type = NLA_NUL_STRING, .len = IP_VS_PENAME_MAXLEN }, [IPVS_SVC_ATTR_FLAGS] = { .type = NLA_BINARY, @@ -3440,8 +3431,12 @@ static int ip_vs_genl_new_daemon(struct netns_ipvs *ipvs, struct nlattr **attrs) if (ipvs->mixed_address_family_dests > 0) return -EINVAL; + rtnl_lock(); + mutex_lock(&ipvs->sync_mutex); ret = start_sync_thread(ipvs, &c, nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE])); + mutex_unlock(&ipvs->sync_mutex); + rtnl_unlock(); return ret; } @@ -3952,6 +3947,7 @@ static struct notifier_block ip_vs_dst_notifier = { int __net_init ip_vs_control_net_init(struct netns_ipvs *ipvs) { + struct net *net = ipvs->net; int i, idx; /* Initialize rs_table */ @@ -3978,9 +3974,9 @@ int __net_init ip_vs_control_net_init(struct netns_ipvs *ipvs) spin_lock_init(&ipvs->tot_stats.lock); - proc_create("ip_vs", 0, ipvs->net->proc_net, &ip_vs_info_fops); - proc_create("ip_vs_stats", 0, ipvs->net->proc_net, &ip_vs_stats_fops); - proc_create("ip_vs_stats_percpu", 0, ipvs->net->proc_net, + proc_create("ip_vs", 0, net->proc_net, &ip_vs_info_fops); + proc_create("ip_vs_stats", 0, net->proc_net, &ip_vs_stats_fops); + proc_create("ip_vs_stats_percpu", 0, net->proc_net, &ip_vs_stats_percpu_fops); if (ip_vs_control_net_init_sysctl(ipvs)) @@ -3995,11 +3991,13 @@ int __net_init ip_vs_control_net_init(struct netns_ipvs *ipvs) void __net_exit ip_vs_control_net_cleanup(struct netns_ipvs *ipvs) { + struct net *net = ipvs->net; + ip_vs_trash_cleanup(ipvs); ip_vs_control_net_cleanup_sysctl(ipvs); - remove_proc_entry("ip_vs_stats_percpu", ipvs->net->proc_net); - remove_proc_entry("ip_vs_stats", ipvs->net->proc_net); - remove_proc_entry("ip_vs", ipvs->net->proc_net); + remove_proc_entry("ip_vs_stats_percpu", net->proc_net); + remove_proc_entry("ip_vs_stats", net->proc_net); + remove_proc_entry("ip_vs", net->proc_net); free_percpu(ipvs->tot_stats.cpustats); } diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index cec7234b7a1d..803001a45aa1 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -48,7 +48,6 @@ #include #include #include -#include #include /* Used for ntoh_seq and hton_seq */ @@ -1357,9 +1356,15 @@ static void set_mcast_pmtudisc(struct sock *sk, int val) /* * Specifiy default interface for outgoing multicasts */ -static int set_mcast_if(struct sock *sk, struct net_device *dev) +static int set_mcast_if(struct sock *sk, char *ifname) { + struct net_device *dev; struct inet_sock *inet = inet_sk(sk); + struct net *net = sock_net(sk); + + dev = __dev_get_by_name(net, ifname); + if (!dev) + return -ENODEV; if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if) return -EINVAL; @@ -1387,14 +1392,19 @@ static int set_mcast_if(struct sock *sk, struct net_device *dev) * in the in_addr structure passed in as a parameter. */ static int -join_mcast_group(struct sock *sk, struct in_addr *addr, struct net_device *dev) +join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname) { + struct net *net = sock_net(sk); struct ip_mreqn mreq; + struct net_device *dev; int ret; memset(&mreq, 0, sizeof(mreq)); memcpy(&mreq.imr_multiaddr, addr, sizeof(struct in_addr)); + dev = __dev_get_by_name(net, ifname); + if (!dev) + return -ENODEV; if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if) return -EINVAL; @@ -1409,10 +1419,15 @@ join_mcast_group(struct sock *sk, struct in_addr *addr, struct net_device *dev) #ifdef CONFIG_IP_VS_IPV6 static int join_mcast_group6(struct sock *sk, struct in6_addr *addr, - struct net_device *dev) + char *ifname) { + struct net *net = sock_net(sk); + struct net_device *dev; int ret; + dev = __dev_get_by_name(net, ifname); + if (!dev) + return -ENODEV; if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if) return -EINVAL; @@ -1424,18 +1439,24 @@ static int join_mcast_group6(struct sock *sk, struct in6_addr *addr, } #endif -static int bind_mcastif_addr(struct socket *sock, struct net_device *dev) +static int bind_mcastif_addr(struct socket *sock, char *ifname) { + struct net *net = sock_net(sock->sk); + struct net_device *dev; __be32 addr; struct sockaddr_in sin; + dev = __dev_get_by_name(net, ifname); + if (!dev) + return -ENODEV; + addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); if (!addr) pr_err("You probably need to specify IP address on " "multicast interface.\n"); IP_VS_DBG(7, "binding socket with (%s) %pI4\n", - dev->name, &addr); + ifname, &addr); /* Now bind the socket with the address of multicast interface */ sin.sin_family = AF_INET; @@ -1468,8 +1489,7 @@ static void get_mcast_sockaddr(union ipvs_sockaddr *sa, int *salen, /* * Set up sending multicast socket over UDP */ -static int make_send_sock(struct netns_ipvs *ipvs, int id, - struct net_device *dev, struct socket **sock_ret) +static struct socket *make_send_sock(struct netns_ipvs *ipvs, int id) { /* multicast addr */ union ipvs_sockaddr mcast_addr; @@ -1481,10 +1501,9 @@ static int make_send_sock(struct netns_ipvs *ipvs, int id, IPPROTO_UDP, &sock); if (result < 0) { pr_err("Error during creation of socket; terminating\n"); - goto error; + return ERR_PTR(result); } - *sock_ret = sock; - result = set_mcast_if(sock->sk, dev); + result = set_mcast_if(sock->sk, ipvs->mcfg.mcast_ifn); if (result < 0) { pr_err("Error setting outbound mcast interface\n"); goto error; @@ -1499,7 +1518,7 @@ static int make_send_sock(struct netns_ipvs *ipvs, int id, set_sock_size(sock->sk, 1, result); if (AF_INET == ipvs->mcfg.mcast_af) - result = bind_mcastif_addr(sock, dev); + result = bind_mcastif_addr(sock, ipvs->mcfg.mcast_ifn); else result = 0; if (result < 0) { @@ -1515,18 +1534,18 @@ static int make_send_sock(struct netns_ipvs *ipvs, int id, goto error; } - return 0; + return sock; error: - return result; + sock_release(sock); + return ERR_PTR(result); } /* * Set up receiving multicast socket over UDP */ -static int make_receive_sock(struct netns_ipvs *ipvs, int id, - struct net_device *dev, struct socket **sock_ret) +static struct socket *make_receive_sock(struct netns_ipvs *ipvs, int id) { /* multicast addr */ union ipvs_sockaddr mcast_addr; @@ -1538,9 +1557,8 @@ static int make_receive_sock(struct netns_ipvs *ipvs, int id, IPPROTO_UDP, &sock); if (result < 0) { pr_err("Error during creation of socket; terminating\n"); - goto error; + return ERR_PTR(result); } - *sock_ret = sock; /* it is equivalent to the REUSEADDR option in user-space */ sock->sk->sk_reuse = SK_CAN_REUSE; result = sysctl_sync_sock_size(ipvs); @@ -1548,7 +1566,6 @@ static int make_receive_sock(struct netns_ipvs *ipvs, int id, set_sock_size(sock->sk, 0, result); get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->bcfg, id); - sock->sk->sk_bound_dev_if = dev->ifindex; result = sock->ops->bind(sock, (struct sockaddr *)&mcast_addr, salen); if (result < 0) { pr_err("Error binding to the multicast addr\n"); @@ -1559,20 +1576,21 @@ static int make_receive_sock(struct netns_ipvs *ipvs, int id, #ifdef CONFIG_IP_VS_IPV6 if (ipvs->bcfg.mcast_af == AF_INET6) result = join_mcast_group6(sock->sk, &mcast_addr.in6.sin6_addr, - dev); + ipvs->bcfg.mcast_ifn); else #endif result = join_mcast_group(sock->sk, &mcast_addr.in.sin_addr, - dev); + ipvs->bcfg.mcast_ifn); if (result < 0) { pr_err("Error joining to the multicast group\n"); goto error; } - return 0; + return sock; error: - return result; + sock_release(sock); + return ERR_PTR(result); } @@ -1757,12 +1775,13 @@ static int sync_thread_backup(void *data) int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c, int state) { - struct ip_vs_sync_thread_data *tinfo = NULL; + struct ip_vs_sync_thread_data *tinfo; struct task_struct **array = NULL, *task; + struct socket *sock; struct net_device *dev; char *name; int (*threadfn)(void *data); - int id = 0, count, hlen; + int id, count, hlen; int result = -ENOMEM; u16 mtu, min_mtu; @@ -1770,18 +1789,6 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c, IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %Zd bytes\n", sizeof(struct ip_vs_sync_conn_v0)); - /* Do not hold one mutex and then to block on another */ - for (;;) { - rtnl_lock(); - if (mutex_trylock(&ipvs->sync_mutex)) - break; - rtnl_unlock(); - mutex_lock(&ipvs->sync_mutex); - if (rtnl_trylock()) - break; - mutex_unlock(&ipvs->sync_mutex); - } - if (!ipvs->sync_state) { count = clamp(sysctl_sync_ports(ipvs), 1, IPVS_SYNC_PORTS_MAX); ipvs->threads_mask = count - 1; @@ -1800,8 +1807,7 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c, dev = __dev_get_by_name(ipvs->net, c->mcast_ifn); if (!dev) { pr_err("Unknown mcast interface: %s\n", c->mcast_ifn); - result = -ENODEV; - goto out_early; + return -ENODEV; } hlen = (AF_INET6 == c->mcast_af) ? sizeof(struct ipv6hdr) + sizeof(struct udphdr) : @@ -1818,30 +1824,26 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c, c->sync_maxlen = mtu - hlen; if (state == IP_VS_STATE_MASTER) { - result = -EEXIST; if (ipvs->ms) - goto out_early; + return -EEXIST; ipvs->mcfg = *c; name = "ipvs-m:%d:%d"; threadfn = sync_thread_master; } else if (state == IP_VS_STATE_BACKUP) { - result = -EEXIST; if (ipvs->backup_threads) - goto out_early; + return -EEXIST; ipvs->bcfg = *c; name = "ipvs-b:%d:%d"; threadfn = sync_thread_backup; } else { - result = -EINVAL; - goto out_early; + return -EINVAL; } if (state == IP_VS_STATE_MASTER) { struct ipvs_master_sync_state *ms; - result = -ENOMEM; ipvs->ms = kzalloc(count * sizeof(ipvs->ms[0]), GFP_KERNEL); if (!ipvs->ms) goto out; @@ -1857,38 +1859,39 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c, } else { array = kzalloc(count * sizeof(struct task_struct *), GFP_KERNEL); - result = -ENOMEM; if (!array) goto out; } + tinfo = NULL; for (id = 0; id < count; id++) { - result = -ENOMEM; + if (state == IP_VS_STATE_MASTER) + sock = make_send_sock(ipvs, id); + else + sock = make_receive_sock(ipvs, id); + if (IS_ERR(sock)) { + result = PTR_ERR(sock); + goto outtinfo; + } tinfo = kmalloc(sizeof(*tinfo), GFP_KERNEL); if (!tinfo) - goto out; + goto outsocket; tinfo->ipvs = ipvs; - tinfo->sock = NULL; + tinfo->sock = sock; if (state == IP_VS_STATE_BACKUP) { tinfo->buf = kmalloc(ipvs->bcfg.sync_maxlen, GFP_KERNEL); if (!tinfo->buf) - goto out; + goto outtinfo; } else { tinfo->buf = NULL; } tinfo->id = id; - if (state == IP_VS_STATE_MASTER) - result = make_send_sock(ipvs, id, dev, &tinfo->sock); - else - result = make_receive_sock(ipvs, id, dev, &tinfo->sock); - if (result < 0) - goto out; task = kthread_run(threadfn, tinfo, name, ipvs->gen, id); if (IS_ERR(task)) { result = PTR_ERR(task); - goto out; + goto outtinfo; } tinfo = NULL; if (state == IP_VS_STATE_MASTER) @@ -1905,20 +1908,20 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c, ipvs->sync_state |= state; spin_unlock_bh(&ipvs->sync_buff_lock); - mutex_unlock(&ipvs->sync_mutex); - rtnl_unlock(); - /* increase the module use count */ ip_vs_use_count_inc(); return 0; -out: - /* We do not need RTNL lock anymore, release it here so that - * sock_release below and in the kthreads can use rtnl_lock - * to leave the mcast group. - */ - rtnl_unlock(); +outsocket: + sock_release(sock); + +outtinfo: + if (tinfo) { + sock_release(tinfo->sock); + kfree(tinfo->buf); + kfree(tinfo); + } count = id; while (count-- > 0) { if (state == IP_VS_STATE_MASTER) @@ -1926,23 +1929,13 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c, else kthread_stop(array[count]); } + kfree(array); + +out: if (!(ipvs->sync_state & IP_VS_STATE_MASTER)) { kfree(ipvs->ms); ipvs->ms = NULL; } - mutex_unlock(&ipvs->sync_mutex); - if (tinfo) { - if (tinfo->sock) - sock_release(tinfo->sock); - kfree(tinfo->buf); - kfree(tinfo); - } - kfree(array); - return result; - -out_early: - mutex_unlock(&ipvs->sync_mutex); - rtnl_unlock(); return result; } diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0610e8cfe6be..2efe0500bba9 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -719,7 +719,6 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, * least once for the stats anyway. */ rcu_read_lock_bh(); - begin: hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { ct = nf_ct_tuplehash_to_ctrack(h); if (ct != ignored_conntrack && @@ -731,12 +730,6 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, } NF_CT_STAT_INC(net, searched); } - - if (get_nulls_value(n) != hash) { - NF_CT_STAT_INC(net, search_restart); - goto begin; - } - rcu_read_unlock_bh(); return 0; diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index f3b92ce463b0..4e78c57b818f 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -200,7 +200,6 @@ void nf_conntrack_unregister_notifier(struct net *net, BUG_ON(notify != new); RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); mutex_unlock(&nf_ct_ecache_mutex); - /* synchronize_rcu() is called from ctnetlink_exit. */ } EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); @@ -237,7 +236,6 @@ void nf_ct_expect_unregister_notifier(struct net *net, BUG_ON(notify != new); RCU_INIT_POINTER(net->ct.nf_expect_event_cb, NULL); mutex_unlock(&nf_ct_ecache_mutex); - /* synchronize_rcu() is called from ctnetlink_exit. */ } EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index a91f8bd51d05..acf5c7b3f378 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -395,7 +395,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) struct net *net = nf_ct_exp_net(expect); struct hlist_node *next; unsigned int h; - int ret = 0; + int ret = 1; if (!master_help) { ret = -ESHUTDOWN; @@ -445,7 +445,7 @@ int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, spin_lock_bh(&nf_conntrack_expect_lock); ret = __nf_ct_expect_check(expect); - if (ret < 0) + if (ret <= 0) goto out; ret = nf_ct_expect_insert(expect); @@ -560,7 +560,7 @@ static int exp_seq_show(struct seq_file *s, void *v) helper = rcu_dereference(nfct_help(expect->master)->helper); if (helper) { seq_printf(s, "%s%s", expect->flags ? " " : "", helper->name); - if (helper->expect_policy[expect->class].name[0]) + if (helper->expect_policy[expect->class].name) seq_printf(s, "/%s", helper->expect_policy[expect->class].name); } diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index 531ca55f1af6..1a9545965c0d 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c @@ -53,11 +53,7 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, rcu_read_lock(); t = rcu_dereference(nf_ct_ext_types[id]); - if (!t) { - rcu_read_unlock(); - return NULL; - } - + BUG_ON(t == NULL); off = ALIGN(sizeof(struct nf_ct_ext), t->align); len = off + t->len + var_alloc_len; alloc_size = t->alloc_size + var_alloc_len; @@ -92,10 +88,7 @@ void *__nf_ct_ext_add_length(struct nf_conn *ct, enum nf_ct_ext_id id, rcu_read_lock(); t = rcu_dereference(nf_ct_ext_types[id]); - if (!t) { - rcu_read_unlock(); - return NULL; - } + BUG_ON(t == NULL); newoff = ALIGN(old->len, t->align); newlen = newoff + t->len + var_alloc_len; @@ -193,6 +186,6 @@ void nf_ct_extend_unregister(struct nf_ct_ext_type *type) RCU_INIT_POINTER(nf_ct_ext_types[type->id], NULL); update_alloc_size(type); mutex_unlock(&nf_ct_ext_type_mutex); - synchronize_rcu(); + rcu_barrier(); /* Wait for completion of call_rcu()'s */ } EXPORT_SYMBOL_GPL(nf_ct_extend_unregister); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index c68e020427ab..9f5272968abb 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -45,8 +45,6 @@ #include #include #include -#include -#include #ifdef CONFIG_NF_NAT_NEEDED #include #include @@ -887,13 +885,8 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) } out: local_bh_enable(); - if (last) { - /* nf ct hash resize happened, now clear the leftover. */ - if ((struct nf_conn *)cb->args[1] == last) - cb->args[1] = 0; - + if (last) nf_ct_put(last); - } return skb->len; } @@ -1004,8 +997,9 @@ static const struct nla_policy tuple_nla_policy[CTA_TUPLE_MAX+1] = { static int ctnetlink_parse_tuple(const struct nlattr * const cda[], - struct nf_conntrack_tuple *tuple, u32 type, - u_int8_t l3num, struct nf_conntrack_zone *zone) + struct nf_conntrack_tuple *tuple, + enum ctattr_type type, u_int8_t l3num, + struct nf_conntrack_zone *zone) { struct nlattr *tb[CTA_TUPLE_MAX+1]; int err; @@ -1804,8 +1798,6 @@ ctnetlink_create_conntrack(struct net *net, nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); nf_ct_labels_ext_add(ct); - nfct_seqadj_ext_add(ct); - nfct_synproxy_ext_add(ct); /* we must add conntrack extensions before confirmation. */ ct->status |= IPS_CONFIRMED; @@ -2420,7 +2412,7 @@ static struct nfnl_ct_hook ctnetlink_glue_hook = { static inline int ctnetlink_exp_dump_tuple(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple, - u32 type) + enum ctattr_expect type) { struct nlattr *nest_parms; @@ -3419,7 +3411,6 @@ static void __exit ctnetlink_exit(void) #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT RCU_INIT_POINTER(nfnl_ct_hook, NULL); #endif - synchronize_rcu(); } module_init(ctnetlink_init); diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 99d0e9261a64..fce1b1cca32d 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -244,14 +244,14 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = * We currently ignore Sync packets * * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ - sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, + sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, }, [DCCP_PKT_SYNCACK] = { /* * We currently ignore SyncAck packets * * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ - sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, + sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, }, }, [CT_DCCP_ROLE_SERVER] = { @@ -372,14 +372,14 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = * We currently ignore Sync packets * * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ - sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, + sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, }, [DCCP_PKT_SYNCACK] = { /* * We currently ignore SyncAck packets * * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ - sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, + sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, }, }, }; diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 1665c2159e4b..885b4aba3695 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1434,12 +1434,9 @@ static int process_sip_request(struct sk_buff *skb, unsigned int protoff, handler = &sip_handlers[i]; if (handler->request == NULL) continue; - if (*datalen < handler->len + 2 || + if (*datalen < handler->len || strncasecmp(*dptr, handler->method, handler->len)) continue; - if ((*dptr)[handler->len] != ' ' || - !isalpha((*dptr)[handler->len+1])) - continue; if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ, &matchoff, &matchlen) <= 0) { diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index f94a2e1172f0..a5d41dfa9f05 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -401,7 +401,7 @@ static int nf_log_proc_dostring(struct ctl_table *table, int write, size_t size = *lenp; int r = 0; int tindex = (unsigned long)table->extra1; - struct net *net = table->extra2; + struct net *net = current->nsproxy->net_ns; if (write) { if (size > sizeof(buf)) @@ -422,17 +422,14 @@ static int nf_log_proc_dostring(struct ctl_table *table, int write, rcu_assign_pointer(net->nf.nf_loggers[tindex], logger); mutex_unlock(&nf_log_mutex); } else { - struct ctl_table tmp = *table; - - tmp.data = buf; mutex_lock(&nf_log_mutex); logger = nft_log_dereference(net->nf.nf_loggers[tindex]); if (!logger) - strlcpy(buf, "NONE", sizeof(buf)); + table->data = "NONE"; else - strlcpy(buf, logger->name, sizeof(buf)); + table->data = logger->name; + r = proc_dostring(table, write, buffer, lenp, ppos); mutex_unlock(&nf_log_mutex); - r = proc_dostring(&tmp, write, buffer, lenp, ppos); } return r; @@ -456,6 +453,7 @@ static int netfilter_log_sysctl_init(struct net *net) 3, "%d", i); nf_log_sysctl_table[i].procname = nf_log_sysctl_fnames[i]; + nf_log_sysctl_table[i].data = NULL; nf_log_sysctl_table[i].maxlen = NFLOGGER_NAME_LEN; nf_log_sysctl_table[i].mode = 0644; nf_log_sysctl_table[i].proc_handler = @@ -465,9 +463,6 @@ static int netfilter_log_sysctl_init(struct net *net) } } - for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) - table[i].extra2 = net; - net->nf.nf_log_dir_header = register_net_sysctl(net, "net/netfilter/nf_log", table); diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 44516c90118a..06a9f45771ab 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -892,8 +892,6 @@ static void __exit nf_nat_cleanup(void) #ifdef CONFIG_XFRM RCU_INIT_POINTER(nf_nat_decode_session_hook, NULL); #endif - synchronize_rcu(); - for (i = 0; i < NFPROTO_NUMPROTO; i++) kfree(nf_nat_l4protos[i]); synchronize_net(); diff --git a/net/netfilter/nf_nat_proto_common.c b/net/netfilter/nf_nat_proto_common.c index 7d7466dbf663..fbce552a796e 100644 --- a/net/netfilter/nf_nat_proto_common.c +++ b/net/netfilter/nf_nat_proto_common.c @@ -41,7 +41,7 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, const struct nf_conn *ct, u16 *rover) { - unsigned int range_size, min, max, i; + unsigned int range_size, min, i; __be16 *portptr; u_int16_t off; @@ -71,10 +71,7 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, } } else { min = ntohs(range->min_proto.all); - max = ntohs(range->max_proto.all); - if (unlikely(max < min)) - swap(max, min); - range_size = max - min + 1; + range_size = ntohs(range->max_proto.all) - min + 1; } if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) { diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index b19ad20a705c..5baa8e24e6ac 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -26,21 +26,23 @@ * Once the queue is registered it must reinject all packets it * receives, no matter what. */ +static const struct nf_queue_handler __rcu *queue_handler __read_mostly; /* return EBUSY when somebody else is registered, return EEXIST if the * same handler is registered, return 0 in case of success. */ -void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh) +void nf_register_queue_handler(const struct nf_queue_handler *qh) { /* should never happen, we only have one queueing backend in kernel */ - WARN_ON(rcu_access_pointer(net->nf.queue_handler)); - rcu_assign_pointer(net->nf.queue_handler, qh); + WARN_ON(rcu_access_pointer(queue_handler)); + rcu_assign_pointer(queue_handler, qh); } EXPORT_SYMBOL(nf_register_queue_handler); /* The caller must flush their queue before this */ -void nf_unregister_queue_handler(struct net *net) +void nf_unregister_queue_handler(void) { - RCU_INIT_POINTER(net->nf.queue_handler, NULL); + RCU_INIT_POINTER(queue_handler, NULL); + synchronize_rcu(); } EXPORT_SYMBOL(nf_unregister_queue_handler); @@ -101,7 +103,7 @@ void nf_queue_nf_hook_drop(struct net *net, struct nf_hook_ops *ops) const struct nf_queue_handler *qh; rcu_read_lock(); - qh = rcu_dereference(net->nf.queue_handler); + qh = rcu_dereference(queue_handler); if (qh) qh->nf_hook_drop(net, ops); rcu_read_unlock(); @@ -120,10 +122,9 @@ int nf_queue(struct sk_buff *skb, struct nf_queue_entry *entry = NULL; const struct nf_afinfo *afinfo; const struct nf_queue_handler *qh; - struct net *net = state->net; /* QUEUE == DROP if no one is waiting, to be safe. */ - qh = rcu_dereference(net->nf.queue_handler); + qh = rcu_dereference(queue_handler); if (!qh) { status = -ESRCH; goto err; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 120e9ae04db3..2cb429d34c03 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1996,7 +1996,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx, * is called on error from nf_tables_newrule(). */ expr = nft_expr_first(rule); - while (expr != nft_expr_last(rule) && expr->ops) { + while (expr->ops && expr != nft_expr_last(rule)) { nf_tables_expr_destroy(ctx, expr); expr = nft_expr_next(expr); } diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 99bc2f87a974..f3695a497408 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -167,8 +167,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv) switch (regs.verdict.code) { case NFT_JUMP: - if (WARN_ON_ONCE(stackptr >= NFT_JUMP_STACK_SIZE)) - return NF_DROP; + BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE); jumpstack[stackptr].chain = chain; jumpstack[stackptr].rule = rule; jumpstack[stackptr].rulenum = rulenum; diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index ac143ae4f7b6..54330fb5efaf 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -33,13 +32,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Pablo Neira Ayuso "); MODULE_DESCRIPTION("nfnl_cthelper: User-space connection tracking helpers"); -struct nfnl_cthelper { - struct list_head list; - struct nf_conntrack_helper helper; -}; - -static LIST_HEAD(nfnl_cthelper_list); - static int nfnl_userspace_cthelper(struct sk_buff *skb, unsigned int protoff, struct nf_conn *ct, enum ip_conntrack_info ctinfo) @@ -169,7 +161,6 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, int i, ret; struct nf_conntrack_expect_policy *expect_policy; struct nlattr *tb[NFCTH_POLICY_SET_MAX+1]; - unsigned int class_max; ret = nla_parse_nested(tb, NFCTH_POLICY_SET_MAX, attr, nfnl_cthelper_expect_policy_set); @@ -179,18 +170,19 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, if (!tb[NFCTH_POLICY_SET_NUM]) return -EINVAL; - class_max = ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM])); - if (class_max == 0) - return -EINVAL; - if (class_max > NF_CT_MAX_EXPECT_CLASSES) + helper->expect_class_max = + ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM])); + + if (helper->expect_class_max != 0 && + helper->expect_class_max > NF_CT_MAX_EXPECT_CLASSES) return -EOVERFLOW; expect_policy = kzalloc(sizeof(struct nf_conntrack_expect_policy) * - class_max, GFP_KERNEL); + helper->expect_class_max, GFP_KERNEL); if (expect_policy == NULL) return -ENOMEM; - for (i = 0; i < class_max; i++) { + for (i=0; iexpect_class_max; i++) { if (!tb[NFCTH_POLICY_SET+i]) goto err; @@ -199,8 +191,6 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, if (ret < 0) goto err; } - - helper->expect_class_max = class_max - 1; helper->expect_policy = expect_policy; return 0; err: @@ -213,20 +203,18 @@ nfnl_cthelper_create(const struct nlattr * const tb[], struct nf_conntrack_tuple *tuple) { struct nf_conntrack_helper *helper; - struct nfnl_cthelper *nfcth; int ret; if (!tb[NFCTH_TUPLE] || !tb[NFCTH_POLICY] || !tb[NFCTH_PRIV_DATA_LEN]) return -EINVAL; - nfcth = kzalloc(sizeof(*nfcth), GFP_KERNEL); - if (nfcth == NULL) + helper = kzalloc(sizeof(struct nf_conntrack_helper), GFP_KERNEL); + if (helper == NULL) return -ENOMEM; - helper = &nfcth->helper; ret = nfnl_cthelper_parse_expect_policy(helper, tb[NFCTH_POLICY]); if (ret < 0) - goto err1; + goto err; strncpy(helper->name, nla_data(tb[NFCTH_NAME]), NF_CT_HELPER_NAME_LEN); helper->data_len = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN])); @@ -257,100 +245,14 @@ nfnl_cthelper_create(const struct nlattr * const tb[], ret = nf_conntrack_helper_register(helper); if (ret < 0) - goto err2; + goto err; - list_add_tail(&nfcth->list, &nfnl_cthelper_list); return 0; -err2: - kfree(helper->expect_policy); -err1: - kfree(nfcth); +err: + kfree(helper); return ret; } -static int -nfnl_cthelper_update_policy_one(const struct nf_conntrack_expect_policy *policy, - struct nf_conntrack_expect_policy *new_policy, - const struct nlattr *attr) -{ - struct nlattr *tb[NFCTH_POLICY_MAX + 1]; - int err; - - err = nla_parse_nested(tb, NFCTH_POLICY_MAX, attr, - nfnl_cthelper_expect_pol); - if (err < 0) - return err; - - if (!tb[NFCTH_POLICY_NAME] || - !tb[NFCTH_POLICY_EXPECT_MAX] || - !tb[NFCTH_POLICY_EXPECT_TIMEOUT]) - return -EINVAL; - - if (nla_strcmp(tb[NFCTH_POLICY_NAME], policy->name)) - return -EBUSY; - - new_policy->max_expected = - ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX])); - new_policy->timeout = - ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_TIMEOUT])); - - return 0; -} - -static int nfnl_cthelper_update_policy_all(struct nlattr *tb[], - struct nf_conntrack_helper *helper) -{ - struct nf_conntrack_expect_policy new_policy[helper->expect_class_max + 1]; - struct nf_conntrack_expect_policy *policy; - int i, err; - - /* Check first that all policy attributes are well-formed, so we don't - * leave things in inconsistent state on errors. - */ - for (i = 0; i < helper->expect_class_max + 1; i++) { - - if (!tb[NFCTH_POLICY_SET + i]) - return -EINVAL; - - err = nfnl_cthelper_update_policy_one(&helper->expect_policy[i], - &new_policy[i], - tb[NFCTH_POLICY_SET + i]); - if (err < 0) - return err; - } - /* Now we can safely update them. */ - for (i = 0; i < helper->expect_class_max + 1; i++) { - policy = (struct nf_conntrack_expect_policy *) - &helper->expect_policy[i]; - policy->max_expected = new_policy->max_expected; - policy->timeout = new_policy->timeout; - } - - return 0; -} - -static int nfnl_cthelper_update_policy(struct nf_conntrack_helper *helper, - const struct nlattr *attr) -{ - struct nlattr *tb[NFCTH_POLICY_SET_MAX + 1]; - unsigned int class_max; - int err; - - err = nla_parse_nested(tb, NFCTH_POLICY_SET_MAX, attr, - nfnl_cthelper_expect_policy_set); - if (err < 0) - return err; - - if (!tb[NFCTH_POLICY_SET_NUM]) - return -EINVAL; - - class_max = ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM])); - if (helper->expect_class_max + 1 != class_max) - return -EBUSY; - - return nfnl_cthelper_update_policy_all(tb, helper); -} - static int nfnl_cthelper_update(const struct nlattr * const tb[], struct nf_conntrack_helper *helper) @@ -361,7 +263,8 @@ nfnl_cthelper_update(const struct nlattr * const tb[], return -EBUSY; if (tb[NFCTH_POLICY]) { - ret = nfnl_cthelper_update_policy(helper, tb[NFCTH_POLICY]); + ret = nfnl_cthelper_parse_expect_policy(helper, + tb[NFCTH_POLICY]); if (ret < 0) return ret; } @@ -390,11 +293,7 @@ nfnl_cthelper_new(struct sock *nfnl, struct sk_buff *skb, const char *helper_name; struct nf_conntrack_helper *cur, *helper = NULL; struct nf_conntrack_tuple tuple; - struct nfnl_cthelper *nlcth; - int ret = 0; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; + int ret = 0, i; if (!tb[NFCTH_NAME] || !tb[NFCTH_TUPLE]) return -EINVAL; @@ -405,22 +304,31 @@ nfnl_cthelper_new(struct sock *nfnl, struct sk_buff *skb, if (ret < 0) return ret; - list_for_each_entry(nlcth, &nfnl_cthelper_list, list) { - cur = &nlcth->helper; + rcu_read_lock(); + for (i = 0; i < nf_ct_helper_hsize && !helper; i++) { + hlist_for_each_entry_rcu(cur, &nf_ct_helper_hash[i], hnode) { - if (strncmp(cur->name, helper_name, NF_CT_HELPER_NAME_LEN)) - continue; + /* skip non-userspace conntrack helpers. */ + if (!(cur->flags & NF_CT_HELPER_F_USERSPACE)) + continue; - if ((tuple.src.l3num != cur->tuple.src.l3num || - tuple.dst.protonum != cur->tuple.dst.protonum)) - continue; + if (strncmp(cur->name, helper_name, + NF_CT_HELPER_NAME_LEN) != 0) + continue; - if (nlh->nlmsg_flags & NLM_F_EXCL) - return -EEXIST; + if ((tuple.src.l3num != cur->tuple.src.l3num || + tuple.dst.protonum != cur->tuple.dst.protonum)) + continue; - helper = cur; - break; + if (nlh->nlmsg_flags & NLM_F_EXCL) { + ret = -EEXIST; + goto err; + } + helper = cur; + break; + } } + rcu_read_unlock(); if (helper == NULL) ret = nfnl_cthelper_create(tb, &tuple); @@ -428,6 +336,9 @@ nfnl_cthelper_new(struct sock *nfnl, struct sk_buff *skb, ret = nfnl_cthelper_update(tb, helper); return ret; +err: + rcu_read_unlock(); + return ret; } static int @@ -466,10 +377,10 @@ nfnl_cthelper_dump_policy(struct sk_buff *skb, goto nla_put_failure; if (nla_put_be32(skb, NFCTH_POLICY_SET_NUM, - htonl(helper->expect_class_max + 1))) + htonl(helper->expect_class_max))) goto nla_put_failure; - for (i = 0; i < helper->expect_class_max + 1; i++) { + for (i=0; iexpect_class_max; i++) { nest_parms2 = nla_nest_start(skb, (NFCTH_POLICY_SET+i) | NLA_F_NESTED); if (nest_parms2 == NULL) @@ -591,17 +502,13 @@ static int nfnl_cthelper_get(struct sock *nfnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const tb[]) { - int ret = -ENOENT; + int ret = -ENOENT, i; struct nf_conntrack_helper *cur; struct sk_buff *skb2; char *helper_name = NULL; struct nf_conntrack_tuple tuple; - struct nfnl_cthelper *nlcth; bool tuple_set = false; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (nlh->nlmsg_flags & NLM_F_DUMP) { struct netlink_dump_control c = { .dump = nfnl_cthelper_dump_table, @@ -620,39 +527,45 @@ nfnl_cthelper_get(struct sock *nfnl, struct sk_buff *skb, tuple_set = true; } - list_for_each_entry(nlcth, &nfnl_cthelper_list, list) { - cur = &nlcth->helper; - if (helper_name && - strncmp(cur->name, helper_name, NF_CT_HELPER_NAME_LEN)) - continue; + for (i = 0; i < nf_ct_helper_hsize; i++) { + hlist_for_each_entry_rcu(cur, &nf_ct_helper_hash[i], hnode) { - if (tuple_set && - (tuple.src.l3num != cur->tuple.src.l3num || - tuple.dst.protonum != cur->tuple.dst.protonum)) - continue; + /* skip non-userspace conntrack helpers. */ + if (!(cur->flags & NF_CT_HELPER_F_USERSPACE)) + continue; - skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (skb2 == NULL) { - ret = -ENOMEM; - break; - } + if (helper_name && strncmp(cur->name, helper_name, + NF_CT_HELPER_NAME_LEN) != 0) { + continue; + } + if (tuple_set && + (tuple.src.l3num != cur->tuple.src.l3num || + tuple.dst.protonum != cur->tuple.dst.protonum)) + continue; - ret = nfnl_cthelper_fill_info(skb2, NETLINK_CB(skb).portid, - nlh->nlmsg_seq, - NFNL_MSG_TYPE(nlh->nlmsg_type), - NFNL_MSG_CTHELPER_NEW, cur); - if (ret <= 0) { - kfree_skb(skb2); - break; - } + skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (skb2 == NULL) { + ret = -ENOMEM; + break; + } + + ret = nfnl_cthelper_fill_info(skb2, NETLINK_CB(skb).portid, + nlh->nlmsg_seq, + NFNL_MSG_TYPE(nlh->nlmsg_type), + NFNL_MSG_CTHELPER_NEW, cur); + if (ret <= 0) { + kfree_skb(skb2); + break; + } - ret = netlink_unicast(nfnl, skb2, NETLINK_CB(skb).portid, - MSG_DONTWAIT); - if (ret > 0) - ret = 0; + ret = netlink_unicast(nfnl, skb2, NETLINK_CB(skb).portid, + MSG_DONTWAIT); + if (ret > 0) + ret = 0; - /* this avoids a loop in nfnetlink. */ - return ret == -EAGAIN ? -ENOBUFS : ret; + /* this avoids a loop in nfnetlink. */ + return ret == -EAGAIN ? -ENOBUFS : ret; + } } return ret; } @@ -663,13 +576,10 @@ nfnl_cthelper_del(struct sock *nfnl, struct sk_buff *skb, { char *helper_name = NULL; struct nf_conntrack_helper *cur; + struct hlist_node *tmp; struct nf_conntrack_tuple tuple; bool tuple_set = false, found = false; - struct nfnl_cthelper *nlcth, *n; - int j = 0, ret; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; + int i, j = 0, ret; if (tb[NFCTH_NAME]) helper_name = nla_data(tb[NFCTH_NAME]); @@ -682,27 +592,28 @@ nfnl_cthelper_del(struct sock *nfnl, struct sk_buff *skb, tuple_set = true; } - list_for_each_entry_safe(nlcth, n, &nfnl_cthelper_list, list) { - cur = &nlcth->helper; - j++; - - if (helper_name && - strncmp(cur->name, helper_name, NF_CT_HELPER_NAME_LEN)) - continue; + for (i = 0; i < nf_ct_helper_hsize; i++) { + hlist_for_each_entry_safe(cur, tmp, &nf_ct_helper_hash[i], + hnode) { + /* skip non-userspace conntrack helpers. */ + if (!(cur->flags & NF_CT_HELPER_F_USERSPACE)) + continue; - if (tuple_set && - (tuple.src.l3num != cur->tuple.src.l3num || - tuple.dst.protonum != cur->tuple.dst.protonum)) - continue; + j++; - found = true; - nf_conntrack_helper_unregister(cur); - kfree(cur->expect_policy); + if (helper_name && strncmp(cur->name, helper_name, + NF_CT_HELPER_NAME_LEN) != 0) { + continue; + } + if (tuple_set && + (tuple.src.l3num != cur->tuple.src.l3num || + tuple.dst.protonum != cur->tuple.dst.protonum)) + continue; - list_del(&nlcth->list); - kfree(nlcth); + found = true; + nf_conntrack_helper_unregister(cur); + } } - /* Make sure we return success if we flush and there is no helpers */ return (found || j == 0) ? 0 : -ENOENT; } @@ -751,16 +662,20 @@ static int __init nfnl_cthelper_init(void) static void __exit nfnl_cthelper_exit(void) { struct nf_conntrack_helper *cur; - struct nfnl_cthelper *nlcth, *n; + struct hlist_node *tmp; + int i; nfnetlink_subsys_unregister(&nfnl_cthelper_subsys); - list_for_each_entry_safe(nlcth, n, &nfnl_cthelper_list, list) { - cur = &nlcth->helper; + for (i=0; iflags & NF_CT_HELPER_F_USERSPACE)) + continue; - nf_conntrack_helper_unregister(cur); - kfree(cur->expect_policy); - kfree(nlcth); + nf_conntrack_helper_unregister(cur); + } } } diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index ed9153bd7e73..c7a2d0e1c462 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -611,8 +611,8 @@ static void __exit cttimeout_exit(void) #ifdef CONFIG_NF_CONNTRACK_TIMEOUT RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL); RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL); - synchronize_rcu(); #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ + rcu_barrier(); } module_init(cttimeout_init); diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 54cde78c2718..861c6615253b 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -390,7 +390,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, GFP_ATOMIC); if (!skb) { skb_tx_error(entskb); - goto nlmsg_failure; + return NULL; } nlh = nlmsg_put(skb, 0, 0, @@ -399,7 +399,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, if (!nlh) { skb_tx_error(entskb); kfree_skb(skb); - goto nlmsg_failure; + return NULL; } nfmsg = nlmsg_data(nlh); nfmsg->nfgen_family = entry->state.pf; @@ -501,7 +501,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, if (entskb->tstamp.tv64) { struct nfqnl_msg_packet_timestamp ts; - struct timespec64 kts = ktime_to_timespec64(entskb->tstamp); + struct timespec64 kts = ktime_to_timespec64(skb->tstamp); ts.sec = cpu_to_be64(kts.tv_sec); ts.usec = cpu_to_be64(kts.tv_nsec / NSEC_PER_USEC); @@ -542,17 +542,12 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, } nlh->nlmsg_len = skb->len; - if (seclen) - security_release_secctx(secdata, seclen); return skb; nla_put_failure: skb_tx_error(entskb); kfree_skb(skb); net_err_ratelimited("nf_queue: error creating packet message\n"); -nlmsg_failure: - if (seclen) - security_release_secctx(secdata, seclen); return NULL; } @@ -1053,8 +1048,10 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, struct net *net = sock_net(ctnl); struct nfnl_queue_net *q = nfnl_queue_pernet(net); - queue = verdict_instance_lookup(q, queue_num, - NETLINK_CB(skb).portid); + queue = instance_lookup(q, queue_num); + if (!queue) + queue = verdict_instance_lookup(q, queue_num, + NETLINK_CB(skb).portid); if (IS_ERR(queue)) return PTR_ERR(queue); @@ -1106,9 +1103,6 @@ nfqnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, static const struct nla_policy nfqa_cfg_policy[NFQA_CFG_MAX+1] = { [NFQA_CFG_CMD] = { .len = sizeof(struct nfqnl_msg_config_cmd) }, [NFQA_CFG_PARAMS] = { .len = sizeof(struct nfqnl_msg_config_params) }, - [NFQA_CFG_QUEUE_MAXLEN] = { .type = NLA_U32 }, - [NFQA_CFG_MASK] = { .type = NLA_U32 }, - [NFQA_CFG_FLAGS] = { .type = NLA_U32 }, }; static const struct nf_queue_handler nfqh = { @@ -1385,29 +1379,21 @@ static int __net_init nfnl_queue_net_init(struct net *net) net->nf.proc_netfilter, &nfqnl_file_ops)) return -ENOMEM; #endif - nf_register_queue_handler(net, &nfqh); return 0; } static void __net_exit nfnl_queue_net_exit(struct net *net) { - nf_unregister_queue_handler(net); #ifdef CONFIG_PROC_FS remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter); #endif } -static void nfnl_queue_net_exit_batch(struct list_head *net_exit_list) -{ - synchronize_rcu(); -} - static struct pernet_operations nfnl_queue_net_ops = { - .init = nfnl_queue_net_init, - .exit = nfnl_queue_net_exit, - .exit_batch = nfnl_queue_net_exit_batch, - .id = &nfnl_queue_net_id, - .size = sizeof(struct nfnl_queue_net), + .init = nfnl_queue_net_init, + .exit = nfnl_queue_net_exit, + .id = &nfnl_queue_net_id, + .size = sizeof(struct nfnl_queue_net), }; static int __init nfnetlink_queue_init(void) @@ -1428,6 +1414,7 @@ static int __init nfnetlink_queue_init(void) } register_netdevice_notifier(&nfqnl_dev_notifier); + nf_register_queue_handler(&nfqh); return status; cleanup_netlink_notifier: @@ -1439,6 +1426,7 @@ static int __init nfnetlink_queue_init(void) static void __exit nfnetlink_queue_fini(void) { + nf_unregister_queue_handler(); unregister_netdevice_notifier(&nfqnl_dev_notifier); nfnetlink_subsys_unregister(&nfqnl_subsys); netlink_unregister_notifier(&nfqnl_rtnl_notifier); diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index 0a5df0cbaa28..9dec3bd1b63c 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c @@ -140,8 +140,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx, if (tb[NFTA_DYNSET_TIMEOUT] != NULL) { if (!(set->flags & NFT_SET_TIMEOUT)) return -EINVAL; - timeout = msecs_to_jiffies(be64_to_cpu(nla_get_be64( - tb[NFTA_DYNSET_TIMEOUT]))); + timeout = be64_to_cpu(nla_get_be64(tb[NFTA_DYNSET_TIMEOUT])); } priv->sreg_key = nft_parse_register(tb[NFTA_DYNSET_SREG_KEY]); @@ -228,8 +227,7 @@ static int nft_dynset_dump(struct sk_buff *skb, const struct nft_expr *expr) goto nla_put_failure; if (nla_put_string(skb, NFTA_DYNSET_SET_NAME, priv->set->name)) goto nla_put_failure; - if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT, - cpu_to_be64(jiffies_to_msecs(priv->timeout)))) + if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT, cpu_to_be64(priv->timeout))) goto nla_put_failure; if (priv->expr && nft_expr_dump(skb, NFTA_DYNSET_EXPR, priv->expr)) goto nla_put_failure; diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index a97a5bf716be..9dfaf4d55ee0 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c @@ -151,34 +151,8 @@ void nft_meta_get_eval(const struct nft_expr *expr, else *dest = PACKET_BROADCAST; break; - case NFPROTO_NETDEV: - switch (skb->protocol) { - case htons(ETH_P_IP): { - int noff = skb_network_offset(skb); - struct iphdr *iph, _iph; - - iph = skb_header_pointer(skb, noff, - sizeof(_iph), &_iph); - if (!iph) - goto err; - - if (ipv4_is_multicast(iph->daddr)) - *dest = PACKET_MULTICAST; - else - *dest = PACKET_BROADCAST; - - break; - } - case htons(ETH_P_IPV6): - *dest = PACKET_MULTICAST; - break; - default: - WARN_ON_ONCE(1); - goto err; - } - break; default: - WARN_ON_ONCE(1); + WARN_ON(1); goto err; } break; diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c index 5d189c11d208..61d216eb7917 100644 --- a/net/netfilter/nft_queue.c +++ b/net/netfilter/nft_queue.c @@ -37,7 +37,7 @@ static void nft_queue_eval(const struct nft_expr *expr, if (priv->queues_total > 1) { if (priv->flags & NFT_QUEUE_FLAG_CPU_FANOUT) { - int cpu = raw_smp_processor_id(); + int cpu = smp_processor_id(); queue = priv->queuenum + cpu % priv->queues_total; } else { diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 1f3c305df45d..d4aaad747ea9 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -38,7 +38,7 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module"); -#define XT_PCPU_BLOCK_SIZE 4096 +#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) struct compat_delta { unsigned int offset; /* offset in kernel */ @@ -208,9 +208,6 @@ xt_request_find_match(uint8_t nfproto, const char *name, uint8_t revision) { struct xt_match *match; - if (strnlen(name, XT_EXTENSION_MAXNAMELEN) == XT_EXTENSION_MAXNAMELEN) - return ERR_PTR(-EINVAL); - match = xt_find_match(nfproto, name, revision); if (IS_ERR(match)) { request_module("%st_%s", xt_prefix[nfproto], name); @@ -253,9 +250,6 @@ struct xt_target *xt_request_find_target(u8 af, const char *name, u8 revision) { struct xt_target *target; - if (strnlen(name, XT_EXTENSION_MAXNAMELEN) == XT_EXTENSION_MAXNAMELEN) - return ERR_PTR(-EINVAL); - target = xt_find_target(af, name, revision); if (IS_ERR(target)) { request_module("%st_%s", xt_prefix[af], name); @@ -366,36 +360,6 @@ textify_hooks(char *buf, size_t size, unsigned int mask, uint8_t nfproto) return buf; } -/** - * xt_check_proc_name - check that name is suitable for /proc file creation - * - * @name: file name candidate - * @size: length of buffer - * - * some x_tables modules wish to create a file in /proc. - * This function makes sure that the name is suitable for this - * purpose, it checks that name is NUL terminated and isn't a 'special' - * name, like "..". - * - * returns negative number on error or 0 if name is useable. - */ -int xt_check_proc_name(const char *name, unsigned int size) -{ - if (name[0] == '\0') - return -EINVAL; - - if (strnlen(name, size) == size) - return -ENAMETOOLONG; - - if (strcmp(name, ".") == 0 || - strcmp(name, "..") == 0 || - strchr(name, '/')) - return -EINVAL; - - return 0; -} -EXPORT_SYMBOL(xt_check_proc_name); - int xt_check_match(struct xt_mtchk_param *par, unsigned int size, u_int8_t proto, bool inv_proto) { @@ -451,47 +415,6 @@ int xt_check_match(struct xt_mtchk_param *par, } EXPORT_SYMBOL_GPL(xt_check_match); -/** xt_check_entry_match - check that matches end before start of target - * - * @match: beginning of xt_entry_match - * @target: beginning of this rules target (alleged end of matches) - * @alignment: alignment requirement of match structures - * - * Validates that all matches add up to the beginning of the target, - * and that each match covers at least the base structure size. - * - * Return: 0 on success, negative errno on failure. - */ -static int xt_check_entry_match(const char *match, const char *target, - const size_t alignment) -{ - const struct xt_entry_match *pos; - int length = target - match; - - if (length == 0) /* no matches */ - return 0; - - pos = (struct xt_entry_match *)match; - do { - if ((unsigned long)pos % alignment) - return -EINVAL; - - if (length < (int)sizeof(struct xt_entry_match)) - return -EINVAL; - - if (pos->u.match_size < sizeof(struct xt_entry_match)) - return -EINVAL; - - if (pos->u.match_size > length) - return -EINVAL; - - length -= pos->u.match_size; - pos = ((void *)((char *)(pos) + (pos)->u.match_size)); - } while (length > 0); - - return 0; -} - #ifdef CONFIG_COMPAT int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta) { @@ -561,14 +484,13 @@ int xt_compat_match_offset(const struct xt_match *match) } EXPORT_SYMBOL_GPL(xt_compat_match_offset); -void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, - unsigned int *size) +int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, + unsigned int *size) { const struct xt_match *match = m->u.kernel.match; struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m; int pad, off = xt_compat_match_offset(match); u_int16_t msize = cm->u.user.match_size; - char name[sizeof(m->u.user.name)]; m = *dstptr; memcpy(m, cm, sizeof(*cm)); @@ -582,12 +504,10 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, msize += off; m->u.user.match_size = msize; - strlcpy(name, match->name, sizeof(name)); - module_put(match->me); - strncpy(m->u.user.name, name, sizeof(m->u.user.name)); *size += off; *dstptr += msize; + return 0; } EXPORT_SYMBOL_GPL(xt_compat_match_from_user); @@ -618,175 +538,8 @@ int xt_compat_match_to_user(const struct xt_entry_match *m, return 0; } EXPORT_SYMBOL_GPL(xt_compat_match_to_user); - -/* non-compat version may have padding after verdict */ -struct compat_xt_standard_target { - struct compat_xt_entry_target t; - compat_uint_t verdict; -}; - -int xt_compat_check_entry_offsets(const void *base, const char *elems, - unsigned int target_offset, - unsigned int next_offset) -{ - long size_of_base_struct = elems - (const char *)base; - const struct compat_xt_entry_target *t; - const char *e = base; - - if (target_offset < size_of_base_struct) - return -EINVAL; - - if (target_offset + sizeof(*t) > next_offset) - return -EINVAL; - - t = (void *)(e + target_offset); - if (t->u.target_size < sizeof(*t)) - return -EINVAL; - - if (target_offset + t->u.target_size > next_offset) - return -EINVAL; - - if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 && - COMPAT_XT_ALIGN(target_offset + sizeof(struct compat_xt_standard_target)) != next_offset) - return -EINVAL; - - /* compat_xt_entry match has less strict aligment requirements, - * otherwise they are identical. In case of padding differences - * we need to add compat version of xt_check_entry_match. - */ - BUILD_BUG_ON(sizeof(struct compat_xt_entry_match) != sizeof(struct xt_entry_match)); - - return xt_check_entry_match(elems, base + target_offset, - __alignof__(struct compat_xt_entry_match)); -} -EXPORT_SYMBOL(xt_compat_check_entry_offsets); #endif /* CONFIG_COMPAT */ -/** - * xt_check_entry_offsets - validate arp/ip/ip6t_entry - * - * @base: pointer to arp/ip/ip6t_entry - * @elems: pointer to first xt_entry_match, i.e. ip(6)t_entry->elems - * @target_offset: the arp/ip/ip6_t->target_offset - * @next_offset: the arp/ip/ip6_t->next_offset - * - * validates that target_offset and next_offset are sane and that all - * match sizes (if any) align with the target offset. - * - * This function does not validate the targets or matches themselves, it - * only tests that all the offsets and sizes are correct, that all - * match structures are aligned, and that the last structure ends where - * the target structure begins. - * - * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version. - * - * The arp/ip/ip6t_entry structure @base must have passed following tests: - * - it must point to a valid memory location - * - base to base + next_offset must be accessible, i.e. not exceed allocated - * length. - * - * A well-formed entry looks like this: - * - * ip(6)t_entry match [mtdata] match [mtdata] target [tgdata] ip(6)t_entry - * e->elems[]-----' | | - * matchsize | | - * matchsize | | - * | | - * target_offset---------------------------------' | - * next_offset---------------------------------------------------' - * - * elems[]: flexible array member at end of ip(6)/arpt_entry struct. - * This is where matches (if any) and the target reside. - * target_offset: beginning of target. - * next_offset: start of the next rule; also: size of this rule. - * Since targets have a minimum size, target_offset + minlen <= next_offset. - * - * Every match stores its size, sum of sizes must not exceed target_offset. - * - * Return: 0 on success, negative errno on failure. - */ -int xt_check_entry_offsets(const void *base, - const char *elems, - unsigned int target_offset, - unsigned int next_offset) -{ - long size_of_base_struct = elems - (const char *)base; - const struct xt_entry_target *t; - const char *e = base; - - /* target start is within the ip/ip6/arpt_entry struct */ - if (target_offset < size_of_base_struct) - return -EINVAL; - - if (target_offset + sizeof(*t) > next_offset) - return -EINVAL; - - t = (void *)(e + target_offset); - if (t->u.target_size < sizeof(*t)) - return -EINVAL; - - if (target_offset + t->u.target_size > next_offset) - return -EINVAL; - - if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 && - XT_ALIGN(target_offset + sizeof(struct xt_standard_target)) != next_offset) - return -EINVAL; - - return xt_check_entry_match(elems, base + target_offset, - __alignof__(struct xt_entry_match)); -} -EXPORT_SYMBOL(xt_check_entry_offsets); - -/** - * xt_alloc_entry_offsets - allocate array to store rule head offsets - * - * @size: number of entries - * - * Return: NULL or kmalloc'd or vmalloc'd array - */ -unsigned int *xt_alloc_entry_offsets(unsigned int size) -{ - unsigned int *off; - - off = kcalloc(size, sizeof(unsigned int), GFP_KERNEL | __GFP_NOWARN); - - if (off) - return off; - - if (size < (SIZE_MAX / sizeof(unsigned int))) - off = vmalloc(size * sizeof(unsigned int)); - - return off; -} -EXPORT_SYMBOL(xt_alloc_entry_offsets); - -/** - * xt_find_jump_offset - check if target is a valid jump offset - * - * @offsets: array containing all valid rule start offsets of a rule blob - * @target: the jump target to search for - * @size: entries in @offset - */ -bool xt_find_jump_offset(const unsigned int *offsets, - unsigned int target, unsigned int size) -{ - int m, low = 0, hi = size; - - while (hi > low) { - m = (low + hi) / 2u; - - if (offsets[m] > target) - hi = m; - else if (offsets[m] < target) - low = m + 1; - else - return true; - } - - return false; -} -EXPORT_SYMBOL(xt_find_jump_offset); - int xt_check_target(struct xt_tgchk_param *par, unsigned int size, u_int8_t proto, bool inv_proto) { @@ -837,80 +590,6 @@ int xt_check_target(struct xt_tgchk_param *par, } EXPORT_SYMBOL_GPL(xt_check_target); -/** - * xt_copy_counters_from_user - copy counters and metadata from userspace - * - * @user: src pointer to userspace memory - * @len: alleged size of userspace memory - * @info: where to store the xt_counters_info metadata - * @compat: true if we setsockopt call is done by 32bit task on 64bit kernel - * - * Copies counter meta data from @user and stores it in @info. - * - * vmallocs memory to hold the counters, then copies the counter data - * from @user to the new memory and returns a pointer to it. - * - * If @compat is true, @info gets converted automatically to the 64bit - * representation. - * - * The metadata associated with the counters is stored in @info. - * - * Return: returns pointer that caller has to test via IS_ERR(). - * If IS_ERR is false, caller has to vfree the pointer. - */ -void *xt_copy_counters_from_user(const void __user *user, unsigned int len, - struct xt_counters_info *info, bool compat) -{ - void *mem; - u64 size; - -#ifdef CONFIG_COMPAT - if (compat) { - /* structures only differ in size due to alignment */ - struct compat_xt_counters_info compat_tmp; - - if (len <= sizeof(compat_tmp)) - return ERR_PTR(-EINVAL); - - len -= sizeof(compat_tmp); - if (copy_from_user(&compat_tmp, user, sizeof(compat_tmp)) != 0) - return ERR_PTR(-EFAULT); - - strlcpy(info->name, compat_tmp.name, sizeof(info->name)); - info->num_counters = compat_tmp.num_counters; - user += sizeof(compat_tmp); - } else -#endif - { - if (len <= sizeof(*info)) - return ERR_PTR(-EINVAL); - - len -= sizeof(*info); - if (copy_from_user(info, user, sizeof(*info)) != 0) - return ERR_PTR(-EFAULT); - - info->name[sizeof(info->name) - 1] = '\0'; - user += sizeof(*info); - } - - size = sizeof(struct xt_counters); - size *= info->num_counters; - - if (size != (u64)len) - return ERR_PTR(-EINVAL); - - mem = vmalloc(len); - if (!mem) - return ERR_PTR(-ENOMEM); - - if (copy_from_user(mem, user, len) == 0) - return mem; - - vfree(mem); - return ERR_PTR(-EFAULT); -} -EXPORT_SYMBOL_GPL(xt_copy_counters_from_user); - #ifdef CONFIG_COMPAT int xt_compat_target_offset(const struct xt_target *target) { @@ -926,7 +605,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t; int pad, off = xt_compat_target_offset(target); u_int16_t tsize = ct->u.user.target_size; - char name[sizeof(t->u.user.name)]; t = *dstptr; memcpy(t, ct, sizeof(*ct)); @@ -940,9 +618,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, tsize += off; t->u.user.target_size = tsize; - strlcpy(name, target->name, sizeof(name)); - module_put(target->me); - strncpy(t->u.user.name, name, sizeof(t->u.user.name)); *size += off; *dstptr += tsize; @@ -983,14 +658,8 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size) struct xt_table_info *info = NULL; size_t sz = sizeof(*info) + size; - if (sz < sizeof(*info)) - return NULL; - - if (sz < sizeof(*info)) - return NULL; - /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ - if ((size >> PAGE_SHIFT) + 2 > totalram_pages) + if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages) return NULL; if (sz <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) @@ -1624,59 +1293,6 @@ void xt_proto_fini(struct net *net, u_int8_t af) } EXPORT_SYMBOL_GPL(xt_proto_fini); -/** - * xt_percpu_counter_alloc - allocate x_tables rule counter - * - * @state: pointer to xt_percpu allocation state - * @counter: pointer to counter struct inside the ip(6)/arpt_entry struct - * - * On SMP, the packet counter [ ip(6)t_entry->counters.pcnt ] will then - * contain the address of the real (percpu) counter. - * - * Rule evaluation needs to use xt_get_this_cpu_counter() helper - * to fetch the real percpu counter. - * - * To speed up allocation and improve data locality, a 4kb block is - * allocated. - * - * xt_percpu_counter_alloc_state contains the base address of the - * allocated page and the current sub-offset. - * - * returns false on error. - */ -bool xt_percpu_counter_alloc(struct xt_percpu_counter_alloc_state *state, - struct xt_counters *counter) -{ - BUILD_BUG_ON(XT_PCPU_BLOCK_SIZE < (sizeof(*counter) * 2)); - - if (nr_cpu_ids <= 1) - return true; - - if (!state->mem) { - state->mem = __alloc_percpu(XT_PCPU_BLOCK_SIZE, - XT_PCPU_BLOCK_SIZE); - if (!state->mem) - return false; - } - counter->pcnt = (__force unsigned long)(state->mem + state->off); - state->off += sizeof(*counter); - if (state->off > (XT_PCPU_BLOCK_SIZE - sizeof(*counter))) { - state->mem = NULL; - state->off = 0; - } - return true; -} -EXPORT_SYMBOL_GPL(xt_percpu_counter_alloc); - -void xt_percpu_counter_free(struct xt_counters *counters) -{ - unsigned long pcnt = counters->pcnt; - - if (nr_cpu_ids > 1 && (pcnt & (XT_PCPU_BLOCK_SIZE - 1)) == 0) - free_percpu((void __percpu *)pcnt); -} -EXPORT_SYMBOL_GPL(xt_percpu_counter_free); - static int __net_init xt_net_init(struct net *net) { int i; diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index febcfac7e3df..e7ac07e53b59 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -168,10 +168,8 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, goto err_put_timeout; } timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); - if (!timeout_ext) { + if (timeout_ext == NULL) ret = -ENOMEM; - goto err_put_timeout; - } rcu_read_unlock(); return ret; @@ -203,7 +201,6 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, struct xt_ct_target_info_v1 *info) { struct nf_conntrack_zone zone; - struct nf_conn_help *help; struct nf_conn *ct; int ret = -EOPNOTSUPP; @@ -252,7 +249,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, if (info->timeout[0]) { ret = xt_ct_set_timeout(ct, par, info->timeout); if (ret < 0) - goto err4; + goto err3; } __set_bit(IPS_CONFIRMED_BIT, &ct->status); nf_conntrack_get(&ct->ct_general); @@ -260,10 +257,6 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, info->ct = ct; return 0; -err4: - help = nfct_help(ct); - if (help) - module_put(help->helper->me); err3: nf_ct_tmpl_free(ct); err2: diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c index 1c4b2b28904f..8ff5ec2e5697 100644 --- a/net/netfilter/xt_IDLETIMER.c +++ b/net/netfilter/xt_IDLETIMER.c @@ -329,11 +329,11 @@ static int idletimer_tg_create(struct idletimer_tg_info *info) printk(KERN_WARNING "[%s] Failed to register pm notifier %d\n", __func__, ret); - INIT_WORK(&info->timer->work, idletimer_tg_work); - mod_timer(&info->timer->timer, msecs_to_jiffies(info->timeout * 1000) + jiffies); + INIT_WORK(&info->timer->work, idletimer_tg_work); + return 0; out_free_attr: @@ -418,10 +418,7 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par) pr_debug("timeout value is zero\n"); return -EINVAL; } - if (info->timeout >= INT_MAX / 1000) { - pr_debug("timeout value is too big\n"); - return -EINVAL; - } + if (info->label[0] == '\0' || strnlen(info->label, MAX_IDLETIMER_LABEL_SIZE) == MAX_IDLETIMER_LABEL_SIZE) { diff --git a/net/netfilter/xt_LED.c b/net/netfilter/xt_LED.c index 0858fe17e14a..3ba31c194cce 100644 --- a/net/netfilter/xt_LED.c +++ b/net/netfilter/xt_LED.c @@ -141,11 +141,10 @@ static int led_tg_check(const struct xt_tgchk_param *par) goto exit_alloc; } - /* Since the letinternal timer can be shared between multiple targets, - * always set it up, even if the current target does not need it - */ - setup_timer(&ledinternal->timer, led_timeout_callback, - (unsigned long)ledinternal); + /* See if we need to set up a timer */ + if (ledinfo->delay > 0) + setup_timer(&ledinternal->timer, led_timeout_callback, + (unsigned long)ledinternal); list_add_tail(&ledinternal->list, &xt_led_triggers); @@ -182,7 +181,8 @@ static void led_tg_destroy(const struct xt_tgdtor_param *par) list_del(&ledinternal->list); - del_timer_sync(&ledinternal->timer); + if (ledinfo->delay > 0) + del_timer_sync(&ledinternal->timer); led_trigger_unregister(&ledinternal->netfilter_led_trigger); diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c index 0be96f8475f7..604df6fae6fc 100644 --- a/net/netfilter/xt_RATEEST.c +++ b/net/netfilter/xt_RATEEST.c @@ -40,30 +40,22 @@ static void xt_rateest_hash_insert(struct xt_rateest *est) hlist_add_head(&est->list, &rateest_hash[h]); } -static struct xt_rateest *__xt_rateest_lookup(const char *name) +struct xt_rateest *xt_rateest_lookup(const char *name) { struct xt_rateest *est; unsigned int h; h = xt_rateest_hash(name); + mutex_lock(&xt_rateest_mutex); hlist_for_each_entry(est, &rateest_hash[h], list) { if (strcmp(est->name, name) == 0) { est->refcnt++; + mutex_unlock(&xt_rateest_mutex); return est; } } - - return NULL; -} - -struct xt_rateest *xt_rateest_lookup(const char *name) -{ - struct xt_rateest *est; - - mutex_lock(&xt_rateest_mutex); - est = __xt_rateest_lookup(name); mutex_unlock(&xt_rateest_mutex); - return est; + return NULL; } EXPORT_SYMBOL_GPL(xt_rateest_lookup); @@ -112,10 +104,8 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) rnd_inited = true; } - mutex_lock(&xt_rateest_mutex); - est = __xt_rateest_lookup(info->name); + est = xt_rateest_lookup(info->name); if (est) { - mutex_unlock(&xt_rateest_mutex); /* * If estimator parameters are specified, they must match the * existing estimator. @@ -153,13 +143,11 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) info->est = est; xt_rateest_hash_insert(est); - mutex_unlock(&xt_rateest_mutex); return 0; err2: kfree(est); err1: - mutex_unlock(&xt_rateest_mutex); return ret; } diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 00f798b20b20..b7c43def0dc6 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -104,7 +104,7 @@ tcpmss_mangle_packet(struct sk_buff *skb, tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); tcp_hdrlen = tcph->doff * 4; - if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr)) + if (len < tcp_hdrlen) return -1; if (info->mss == XT_TCPMSS_CLAMP_PMTU) { @@ -156,10 +156,6 @@ tcpmss_mangle_packet(struct sk_buff *skb, if (len > tcp_hdrlen) return 0; - /* tcph->doff has 4 bits, do not wrap it to 0 */ - if (tcp_hdrlen >= 15 * 4) - return 0; - /* * MSS Option not found ?! add it.. */ diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 7381be0cdcdf..178696852bde 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -668,9 +668,8 @@ static int hashlimit_mt_check(const struct xt_mtchk_param *par) if (info->cfg.gc_interval == 0 || info->cfg.expire == 0) return -EINVAL; - ret = xt_check_proc_name(info->name, sizeof(info->name)); - if (ret) - return ret; + if (info->name[sizeof(info->name)-1] != '\0') + return -EINVAL; if (par->family == NFPROTO_IPV4) { if (info->cfg.srcmask > 32 || info->cfg.dstmask > 32) return -EINVAL; diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index 7eae0d0af89a..df8801e02a32 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -70,9 +69,6 @@ static int xt_osf_add_callback(struct sock *ctnl, struct sk_buff *skb, struct xt_osf_finger *kf = NULL, *sf; int err = 0; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (!osf_attrs[OSF_ATTR_FINGER]) return -EINVAL; @@ -116,9 +112,6 @@ static int xt_osf_remove_callback(struct sock *ctnl, struct sk_buff *skb, struct xt_osf_finger *sf; int err = -ENOENT; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (!osf_attrs[OSF_ATTR_FINGER]) return -EINVAL; diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index cd53b861a15c..d725a27743a1 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -364,9 +364,9 @@ static int recent_mt_check(const struct xt_mtchk_param *par, info->hit_count, XT_RECENT_MAX_NSTAMPS - 1); return -EINVAL; } - ret = xt_check_proc_name(info->name, sizeof(info->name)); - if (ret) - return ret; + if (info->name[0] == '\0' || + strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN) + return -EINVAL; if (ip_pkt_list_tot && info->hit_count < ip_pkt_list_tot) nstamp_mask = roundup_pow_of_two(ip_pkt_list_tot) - 1; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index bfa2b6d5b5cf..28cddc85b700 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -824,11 +824,7 @@ int netlbl_sock_setattr(struct sock *sk, */ void netlbl_sock_delattr(struct sock *sk) { - switch (sk->sk_family) { - case AF_INET: - cipso_v4_sock_delattr(sk); - break; - } + cipso_v4_sock_delattr(sk); } /** @@ -991,11 +987,7 @@ int netlbl_req_setattr(struct request_sock *req, */ void netlbl_req_delattr(struct request_sock *req) { - switch (req->rsk_ops->family) { - case AF_INET: - cipso_v4_req_delattr(req); - break; - } + cipso_v4_req_delattr(req); } /** diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 3f33ec44bd28..b0380927f05f 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -1469,16 +1469,6 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb, iface = rcu_dereference(netlbl_unlhsh_def); if (iface == NULL || !iface->valid) goto unlabel_getattr_nolabel; - -#if IS_ENABLED(CONFIG_IPV6) - /* When resolving a fallback label, check the sk_buff version as - * it is possible (e.g. SCTP) to have family = PF_INET6 while - * receiving ip_hdr(skb)->version = 4. - */ - if (family == PF_INET6 && ip_hdr(skb)->version == 4) - family = PF_INET; -#endif /* IPv6 */ - switch (family) { case PF_INET: { struct iphdr *hdr4; diff --git a/net/netlink/Kconfig b/net/netlink/Kconfig index 5d6e8c05b3d4..2c5e95e9bfbd 100644 --- a/net/netlink/Kconfig +++ b/net/netlink/Kconfig @@ -2,6 +2,15 @@ # Netlink Sockets # +config NETLINK_MMAP + bool "NETLINK: mmaped IO" + ---help--- + This option enables support for memory mapped netlink IO. This + reduces overhead by avoiding copying data between kernel- and + userspace. + + If unsure, say N. + config NETLINK_DIAG tristate "NETLINK: socket monitoring interface" default n diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index c6100c677993..b352ba86b0fc 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -62,7 +62,6 @@ #include #include #include -#include #include #include @@ -97,44 +96,6 @@ EXPORT_SYMBOL_GPL(nl_table); static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait); -static struct lock_class_key nlk_cb_mutex_keys[MAX_LINKS]; - -static const char *const nlk_cb_mutex_key_strings[MAX_LINKS + 1] = { - "nlk_cb_mutex-ROUTE", - "nlk_cb_mutex-1", - "nlk_cb_mutex-USERSOCK", - "nlk_cb_mutex-FIREWALL", - "nlk_cb_mutex-SOCK_DIAG", - "nlk_cb_mutex-NFLOG", - "nlk_cb_mutex-XFRM", - "nlk_cb_mutex-SELINUX", - "nlk_cb_mutex-ISCSI", - "nlk_cb_mutex-AUDIT", - "nlk_cb_mutex-FIB_LOOKUP", - "nlk_cb_mutex-CONNECTOR", - "nlk_cb_mutex-NETFILTER", - "nlk_cb_mutex-IP6_FW", - "nlk_cb_mutex-DNRTMSG", - "nlk_cb_mutex-KOBJECT_UEVENT", - "nlk_cb_mutex-GENERIC", - "nlk_cb_mutex-17", - "nlk_cb_mutex-SCSITRANSPORT", - "nlk_cb_mutex-ECRYPTFS", - "nlk_cb_mutex-RDMA", - "nlk_cb_mutex-CRYPTO", - "nlk_cb_mutex-SMC", - "nlk_cb_mutex-23", - "nlk_cb_mutex-24", - "nlk_cb_mutex-25", - "nlk_cb_mutex-26", - "nlk_cb_mutex-27", - "nlk_cb_mutex-28", - "nlk_cb_mutex-29", - "nlk_cb_mutex-30", - "nlk_cb_mutex-31", - "nlk_cb_mutex-MAX_LINKS" -}; - static int netlink_dump(struct sock *sk); static void netlink_skb_destructor(struct sk_buff *skb); @@ -262,12 +223,9 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb, struct sock *sk = skb->sk; int ret = -ENOMEM; - if (!net_eq(dev_net(dev), sock_net(sk))) - return 0; - dev_hold(dev); - if (is_vmalloc_addr(skb->head)) + if (netlink_skb_is_mmaped(skb) || is_vmalloc_addr(skb->head)) nskb = netlink_to_full_skb(skb, GFP_ATOMIC); else nskb = skb_clone(skb, GFP_ATOMIC); @@ -342,8 +300,610 @@ static void netlink_rcv_wake(struct sock *sk) wake_up_interruptible(&nlk->wait); } +#ifdef CONFIG_NETLINK_MMAP +static bool netlink_rx_is_mmaped(struct sock *sk) +{ + return nlk_sk(sk)->rx_ring.pg_vec != NULL; +} + +static bool netlink_tx_is_mmaped(struct sock *sk) +{ + return nlk_sk(sk)->tx_ring.pg_vec != NULL; +} + +static __pure struct page *pgvec_to_page(const void *addr) +{ + if (is_vmalloc_addr(addr)) + return vmalloc_to_page(addr); + else + return virt_to_page(addr); +} + +static void free_pg_vec(void **pg_vec, unsigned int order, unsigned int len) +{ + unsigned int i; + + for (i = 0; i < len; i++) { + if (pg_vec[i] != NULL) { + if (is_vmalloc_addr(pg_vec[i])) + vfree(pg_vec[i]); + else + free_pages((unsigned long)pg_vec[i], order); + } + } + kfree(pg_vec); +} + +static void *alloc_one_pg_vec_page(unsigned long order) +{ + void *buffer; + gfp_t gfp_flags = GFP_KERNEL | __GFP_COMP | __GFP_ZERO | + __GFP_NOWARN | __GFP_NORETRY; + + buffer = (void *)__get_free_pages(gfp_flags, order); + if (buffer != NULL) + return buffer; + + buffer = vzalloc((1 << order) * PAGE_SIZE); + if (buffer != NULL) + return buffer; + + gfp_flags &= ~__GFP_NORETRY; + return (void *)__get_free_pages(gfp_flags, order); +} + +static void **alloc_pg_vec(struct netlink_sock *nlk, + struct nl_mmap_req *req, unsigned int order) +{ + unsigned int block_nr = req->nm_block_nr; + unsigned int i; + void **pg_vec; + + pg_vec = kcalloc(block_nr, sizeof(void *), GFP_KERNEL); + if (pg_vec == NULL) + return NULL; + + for (i = 0; i < block_nr; i++) { + pg_vec[i] = alloc_one_pg_vec_page(order); + if (pg_vec[i] == NULL) + goto err1; + } + + return pg_vec; +err1: + free_pg_vec(pg_vec, order, block_nr); + return NULL; +} + + +static void +__netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, bool tx_ring, void **pg_vec, + unsigned int order) +{ + struct netlink_sock *nlk = nlk_sk(sk); + struct sk_buff_head *queue; + struct netlink_ring *ring; + + queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue; + ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring; + + spin_lock_bh(&queue->lock); + + ring->frame_max = req->nm_frame_nr - 1; + ring->head = 0; + ring->frame_size = req->nm_frame_size; + ring->pg_vec_pages = req->nm_block_size / PAGE_SIZE; + + swap(ring->pg_vec_len, req->nm_block_nr); + swap(ring->pg_vec_order, order); + swap(ring->pg_vec, pg_vec); + + __skb_queue_purge(queue); + spin_unlock_bh(&queue->lock); + + WARN_ON(atomic_read(&nlk->mapped)); + + if (pg_vec) + free_pg_vec(pg_vec, order, req->nm_block_nr); +} + +static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, + bool tx_ring) +{ + struct netlink_sock *nlk = nlk_sk(sk); + struct netlink_ring *ring; + void **pg_vec = NULL; + unsigned int order = 0; + + ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring; + + if (atomic_read(&nlk->mapped)) + return -EBUSY; + if (atomic_read(&ring->pending)) + return -EBUSY; + + if (req->nm_block_nr) { + if (ring->pg_vec != NULL) + return -EBUSY; + + if ((int)req->nm_block_size <= 0) + return -EINVAL; + if (!PAGE_ALIGNED(req->nm_block_size)) + return -EINVAL; + if (req->nm_frame_size < NL_MMAP_HDRLEN) + return -EINVAL; + if (!IS_ALIGNED(req->nm_frame_size, NL_MMAP_MSG_ALIGNMENT)) + return -EINVAL; + + ring->frames_per_block = req->nm_block_size / + req->nm_frame_size; + if (ring->frames_per_block == 0) + return -EINVAL; + if (ring->frames_per_block * req->nm_block_nr != + req->nm_frame_nr) + return -EINVAL; + + order = get_order(req->nm_block_size); + pg_vec = alloc_pg_vec(nlk, req, order); + if (pg_vec == NULL) + return -ENOMEM; + } else { + if (req->nm_frame_nr) + return -EINVAL; + } + + mutex_lock(&nlk->pg_vec_lock); + if (atomic_read(&nlk->mapped) == 0) { + __netlink_set_ring(sk, req, tx_ring, pg_vec, order); + mutex_unlock(&nlk->pg_vec_lock); + return 0; + } + + mutex_unlock(&nlk->pg_vec_lock); + + if (pg_vec) + free_pg_vec(pg_vec, order, req->nm_block_nr); + + return -EBUSY; +} + +static void netlink_mm_open(struct vm_area_struct *vma) +{ + struct file *file = vma->vm_file; + struct socket *sock = file->private_data; + struct sock *sk = sock->sk; + + if (sk) + atomic_inc(&nlk_sk(sk)->mapped); +} + +static void netlink_mm_close(struct vm_area_struct *vma) +{ + struct file *file = vma->vm_file; + struct socket *sock = file->private_data; + struct sock *sk = sock->sk; + + if (sk) + atomic_dec(&nlk_sk(sk)->mapped); +} + +static const struct vm_operations_struct netlink_mmap_ops = { + .open = netlink_mm_open, + .close = netlink_mm_close, +}; + +static int netlink_mmap(struct file *file, struct socket *sock, + struct vm_area_struct *vma) +{ + struct sock *sk = sock->sk; + struct netlink_sock *nlk = nlk_sk(sk); + struct netlink_ring *ring; + unsigned long start, size, expected; + unsigned int i; + int err = -EINVAL; + + if (vma->vm_pgoff) + return -EINVAL; + + mutex_lock(&nlk->pg_vec_lock); + + expected = 0; + for (ring = &nlk->rx_ring; ring <= &nlk->tx_ring; ring++) { + if (ring->pg_vec == NULL) + continue; + expected += ring->pg_vec_len * ring->pg_vec_pages * PAGE_SIZE; + } + + if (expected == 0) + goto out; + + size = vma->vm_end - vma->vm_start; + if (size != expected) + goto out; + + start = vma->vm_start; + for (ring = &nlk->rx_ring; ring <= &nlk->tx_ring; ring++) { + if (ring->pg_vec == NULL) + continue; + + for (i = 0; i < ring->pg_vec_len; i++) { + struct page *page; + void *kaddr = ring->pg_vec[i]; + unsigned int pg_num; + + for (pg_num = 0; pg_num < ring->pg_vec_pages; pg_num++) { + page = pgvec_to_page(kaddr); + err = vm_insert_page(vma, start, page); + if (err < 0) + goto out; + start += PAGE_SIZE; + kaddr += PAGE_SIZE; + } + } + } + + atomic_inc(&nlk->mapped); + vma->vm_ops = &netlink_mmap_ops; + err = 0; +out: + mutex_unlock(&nlk->pg_vec_lock); + return err; +} + +static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr, unsigned int nm_len) +{ +#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 1 + struct page *p_start, *p_end; + + /* First page is flushed through netlink_{get,set}_status */ + p_start = pgvec_to_page(hdr + PAGE_SIZE); + p_end = pgvec_to_page((void *)hdr + NL_MMAP_HDRLEN + nm_len - 1); + while (p_start <= p_end) { + flush_dcache_page(p_start); + p_start++; + } +#endif +} + +static enum nl_mmap_status netlink_get_status(const struct nl_mmap_hdr *hdr) +{ + smp_rmb(); + flush_dcache_page(pgvec_to_page(hdr)); + return hdr->nm_status; +} + +static void netlink_set_status(struct nl_mmap_hdr *hdr, + enum nl_mmap_status status) +{ + smp_mb(); + hdr->nm_status = status; + flush_dcache_page(pgvec_to_page(hdr)); +} + +static struct nl_mmap_hdr * +__netlink_lookup_frame(const struct netlink_ring *ring, unsigned int pos) +{ + unsigned int pg_vec_pos, frame_off; + + pg_vec_pos = pos / ring->frames_per_block; + frame_off = pos % ring->frames_per_block; + + return ring->pg_vec[pg_vec_pos] + (frame_off * ring->frame_size); +} + +static struct nl_mmap_hdr * +netlink_lookup_frame(const struct netlink_ring *ring, unsigned int pos, + enum nl_mmap_status status) +{ + struct nl_mmap_hdr *hdr; + + hdr = __netlink_lookup_frame(ring, pos); + if (netlink_get_status(hdr) != status) + return NULL; + + return hdr; +} + +static struct nl_mmap_hdr * +netlink_current_frame(const struct netlink_ring *ring, + enum nl_mmap_status status) +{ + return netlink_lookup_frame(ring, ring->head, status); +} + +static void netlink_increment_head(struct netlink_ring *ring) +{ + ring->head = ring->head != ring->frame_max ? ring->head + 1 : 0; +} + +static void netlink_forward_ring(struct netlink_ring *ring) +{ + unsigned int head = ring->head; + const struct nl_mmap_hdr *hdr; + + do { + hdr = __netlink_lookup_frame(ring, ring->head); + if (hdr->nm_status == NL_MMAP_STATUS_UNUSED) + break; + if (hdr->nm_status != NL_MMAP_STATUS_SKIP) + break; + netlink_increment_head(ring); + } while (ring->head != head); +} + +static bool netlink_has_valid_frame(struct netlink_ring *ring) +{ + unsigned int head = ring->head, pos = head; + const struct nl_mmap_hdr *hdr; + + do { + hdr = __netlink_lookup_frame(ring, pos); + if (hdr->nm_status == NL_MMAP_STATUS_VALID) + return true; + pos = pos != 0 ? pos - 1 : ring->frame_max; + } while (pos != head); + + return false; +} + +static bool netlink_dump_space(struct netlink_sock *nlk) +{ + struct netlink_ring *ring = &nlk->rx_ring; + struct nl_mmap_hdr *hdr; + unsigned int n; + + hdr = netlink_current_frame(ring, NL_MMAP_STATUS_UNUSED); + if (hdr == NULL) + return false; + + n = ring->head + ring->frame_max / 2; + if (n > ring->frame_max) + n -= ring->frame_max; + + hdr = __netlink_lookup_frame(ring, n); + + return hdr->nm_status == NL_MMAP_STATUS_UNUSED; +} + +static unsigned int netlink_poll(struct file *file, struct socket *sock, + poll_table *wait) +{ + struct sock *sk = sock->sk; + struct netlink_sock *nlk = nlk_sk(sk); + unsigned int mask; + int err; + + if (nlk->rx_ring.pg_vec != NULL) { + /* Memory mapped sockets don't call recvmsg(), so flow control + * for dumps is performed here. A dump is allowed to continue + * if at least half the ring is unused. + */ + while (nlk->cb_running && netlink_dump_space(nlk)) { + err = netlink_dump(sk); + if (err < 0) { + sk->sk_err = -err; + sk->sk_error_report(sk); + break; + } + } + netlink_rcv_wake(sk); + } + + mask = datagram_poll(file, sock, wait); + + /* We could already have received frames in the normal receive + * queue, that will show up as NL_MMAP_STATUS_COPY in the ring, + * so if mask contains pollin/etc already, there's no point + * walking the ring. + */ + if ((mask & (POLLIN | POLLRDNORM)) != (POLLIN | POLLRDNORM)) { + spin_lock_bh(&sk->sk_receive_queue.lock); + if (nlk->rx_ring.pg_vec) { + if (netlink_has_valid_frame(&nlk->rx_ring)) + mask |= POLLIN | POLLRDNORM; + } + spin_unlock_bh(&sk->sk_receive_queue.lock); + } + + spin_lock_bh(&sk->sk_write_queue.lock); + if (nlk->tx_ring.pg_vec) { + if (netlink_current_frame(&nlk->tx_ring, NL_MMAP_STATUS_UNUSED)) + mask |= POLLOUT | POLLWRNORM; + } + spin_unlock_bh(&sk->sk_write_queue.lock); + + return mask; +} + +static struct nl_mmap_hdr *netlink_mmap_hdr(struct sk_buff *skb) +{ + return (struct nl_mmap_hdr *)(skb->head - NL_MMAP_HDRLEN); +} + +static void netlink_ring_setup_skb(struct sk_buff *skb, struct sock *sk, + struct netlink_ring *ring, + struct nl_mmap_hdr *hdr) +{ + unsigned int size; + void *data; + + size = ring->frame_size - NL_MMAP_HDRLEN; + data = (void *)hdr + NL_MMAP_HDRLEN; + + skb->head = data; + skb->data = data; + skb_reset_tail_pointer(skb); + skb->end = skb->tail + size; + skb->len = 0; + + skb->destructor = netlink_skb_destructor; + NETLINK_CB(skb).flags |= NETLINK_SKB_MMAPED; + NETLINK_CB(skb).sk = sk; +} + +static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg, + u32 dst_portid, u32 dst_group, + struct scm_cookie *scm) +{ + struct netlink_sock *nlk = nlk_sk(sk); + struct netlink_ring *ring; + struct nl_mmap_hdr *hdr; + struct sk_buff *skb; + unsigned int maxlen; + int err = 0, len = 0; + + mutex_lock(&nlk->pg_vec_lock); + + ring = &nlk->tx_ring; + maxlen = ring->frame_size - NL_MMAP_HDRLEN; + + do { + unsigned int nm_len; + + hdr = netlink_current_frame(ring, NL_MMAP_STATUS_VALID); + if (hdr == NULL) { + if (!(msg->msg_flags & MSG_DONTWAIT) && + atomic_read(&nlk->tx_ring.pending)) + schedule(); + continue; + } + + nm_len = ACCESS_ONCE(hdr->nm_len); + if (nm_len > maxlen) { + err = -EINVAL; + goto out; + } + + netlink_frame_flush_dcache(hdr, nm_len); + + skb = alloc_skb(nm_len, GFP_KERNEL); + if (skb == NULL) { + err = -ENOBUFS; + goto out; + } + __skb_put(skb, nm_len); + memcpy(skb->data, (void *)hdr + NL_MMAP_HDRLEN, nm_len); + netlink_set_status(hdr, NL_MMAP_STATUS_UNUSED); + + netlink_increment_head(ring); + + NETLINK_CB(skb).portid = nlk->portid; + NETLINK_CB(skb).dst_group = dst_group; + NETLINK_CB(skb).creds = scm->creds; + + err = security_netlink_send(sk, skb); + if (err) { + kfree_skb(skb); + goto out; + } + + if (unlikely(dst_group)) { + atomic_inc(&skb->users); + netlink_broadcast(sk, skb, dst_portid, dst_group, + GFP_KERNEL); + } + err = netlink_unicast(sk, skb, dst_portid, + msg->msg_flags & MSG_DONTWAIT); + if (err < 0) + goto out; + len += err; + + } while (hdr != NULL || + (!(msg->msg_flags & MSG_DONTWAIT) && + atomic_read(&nlk->tx_ring.pending))); + + if (len > 0) + err = len; +out: + mutex_unlock(&nlk->pg_vec_lock); + return err; +} + +static void netlink_queue_mmaped_skb(struct sock *sk, struct sk_buff *skb) +{ + struct nl_mmap_hdr *hdr; + + hdr = netlink_mmap_hdr(skb); + hdr->nm_len = skb->len; + hdr->nm_group = NETLINK_CB(skb).dst_group; + hdr->nm_pid = NETLINK_CB(skb).creds.pid; + hdr->nm_uid = from_kuid(sk_user_ns(sk), NETLINK_CB(skb).creds.uid); + hdr->nm_gid = from_kgid(sk_user_ns(sk), NETLINK_CB(skb).creds.gid); + netlink_frame_flush_dcache(hdr, hdr->nm_len); + netlink_set_status(hdr, NL_MMAP_STATUS_VALID); + + NETLINK_CB(skb).flags |= NETLINK_SKB_DELIVERED; + kfree_skb(skb); +} + +static void netlink_ring_set_copied(struct sock *sk, struct sk_buff *skb) +{ + struct netlink_sock *nlk = nlk_sk(sk); + struct netlink_ring *ring = &nlk->rx_ring; + struct nl_mmap_hdr *hdr; + + spin_lock_bh(&sk->sk_receive_queue.lock); + hdr = netlink_current_frame(ring, NL_MMAP_STATUS_UNUSED); + if (hdr == NULL) { + spin_unlock_bh(&sk->sk_receive_queue.lock); + kfree_skb(skb); + netlink_overrun(sk); + return; + } + netlink_increment_head(ring); + __skb_queue_tail(&sk->sk_receive_queue, skb); + spin_unlock_bh(&sk->sk_receive_queue.lock); + + hdr->nm_len = skb->len; + hdr->nm_group = NETLINK_CB(skb).dst_group; + hdr->nm_pid = NETLINK_CB(skb).creds.pid; + hdr->nm_uid = from_kuid(sk_user_ns(sk), NETLINK_CB(skb).creds.uid); + hdr->nm_gid = from_kgid(sk_user_ns(sk), NETLINK_CB(skb).creds.gid); + netlink_set_status(hdr, NL_MMAP_STATUS_COPY); +} + +#else /* CONFIG_NETLINK_MMAP */ +#define netlink_rx_is_mmaped(sk) false +#define netlink_tx_is_mmaped(sk) false +#define netlink_mmap sock_no_mmap +#define netlink_poll datagram_poll +#define netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, scm) 0 +#endif /* CONFIG_NETLINK_MMAP */ + static void netlink_skb_destructor(struct sk_buff *skb) { +#ifdef CONFIG_NETLINK_MMAP + struct nl_mmap_hdr *hdr; + struct netlink_ring *ring; + struct sock *sk; + + /* If a packet from the kernel to userspace was freed because of an + * error without being delivered to userspace, the kernel must reset + * the status. In the direction userspace to kernel, the status is + * always reset here after the packet was processed and freed. + */ + if (netlink_skb_is_mmaped(skb)) { + hdr = netlink_mmap_hdr(skb); + sk = NETLINK_CB(skb).sk; + + if (NETLINK_CB(skb).flags & NETLINK_SKB_TX) { + netlink_set_status(hdr, NL_MMAP_STATUS_UNUSED); + ring = &nlk_sk(sk)->tx_ring; + } else { + if (!(NETLINK_CB(skb).flags & NETLINK_SKB_DELIVERED)) { + hdr->nm_len = 0; + netlink_set_status(hdr, NL_MMAP_STATUS_VALID); + } + ring = &nlk_sk(sk)->rx_ring; + } + + WARN_ON(atomic_read(&ring->pending) == 0); + atomic_dec(&ring->pending); + sock_put(sk); + + skb->head = NULL; + } +#endif if (is_vmalloc_addr(skb->head)) { if (!skb->cloned || !atomic_dec_return(&(skb_shinfo(skb)->dataref))) @@ -371,11 +931,24 @@ static void netlink_sock_destruct(struct sock *sk) if (nlk->cb_running) { if (nlk->cb.done) nlk->cb.done(&nlk->cb); + module_put(nlk->cb.module); kfree_skb(nlk->cb.skb); } skb_queue_purge(&sk->sk_receive_queue); +#ifdef CONFIG_NETLINK_MMAP + if (1) { + struct nl_mmap_req req; + + memset(&req, 0, sizeof(req)); + if (nlk->rx_ring.pg_vec) + __netlink_set_ring(sk, &req, false, NULL, 0); + memset(&req, 0, sizeof(req)); + if (nlk->tx_ring.pg_vec) + __netlink_set_ring(sk, &req, true, NULL, 0); + } +#endif /* CONFIG_NETLINK_MMAP */ if (!sock_flag(sk, SOCK_DEAD)) { printk(KERN_ERR "Freeing alive netlink socket %p\n", sk); @@ -387,14 +960,6 @@ static void netlink_sock_destruct(struct sock *sk) WARN_ON(nlk_sk(sk)->groups); } -static void netlink_sock_destruct_work(struct work_struct *work) -{ - struct netlink_sock *nlk = container_of(work, struct netlink_sock, - work); - - sk_free(&nlk->sk); -} - /* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on * SMP. Look, when several writers sleep and reader wakes them up, all but one * immediately hit write lock and grab all the cpus. Exclusive sleep solves @@ -627,11 +1192,11 @@ static int __netlink_create(struct net *net, struct socket *sock, } else { nlk->cb_mutex = &nlk->cb_def_mutex; mutex_init(nlk->cb_mutex); - lockdep_set_class_and_name(nlk->cb_mutex, - nlk_cb_mutex_keys + protocol, - nlk_cb_mutex_key_strings[protocol]); } init_waitqueue_head(&nlk->wait); +#ifdef CONFIG_NETLINK_MMAP + mutex_init(&nlk->pg_vec_lock); +#endif sk->sk_destruct = netlink_sock_destruct; sk->sk_protocol = protocol; @@ -655,7 +1220,6 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol, if (protocol < 0 || protocol >= MAX_LINKS) return -EPROTONOSUPPORT; - protocol = array_index_nospec(protocol, MAX_LINKS); netlink_lock_table(); #ifdef CONFIG_MODULES @@ -701,18 +1265,8 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol, static void deferred_put_nlk_sk(struct rcu_head *head) { struct netlink_sock *nlk = container_of(head, struct netlink_sock, rcu); - struct sock *sk = &nlk->sk; - - if (!atomic_dec_and_test(&sk->sk_refcnt)) - return; - if (nlk->cb_running && nlk->cb.done) { - INIT_WORK(&nlk->work, netlink_sock_destruct_work); - schedule_work(&nlk->work); - return; - } - - sk_free(sk); + sock_put(&nlk->sk); } static int netlink_release(struct socket *sock) @@ -986,11 +1540,6 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, return err; } - if (nlk->ngroups == 0) - groups = 0; - else if (nlk->ngroups < 8*sizeof(groups)) - groups &= (1UL << nlk->ngroups) - 1; - bound = nlk->bound; if (bound) { /* Ensure nlk->portid is up-to-date. */ @@ -1061,9 +1610,6 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, if (addr->sa_family != AF_NETLINK) return -EINVAL; - if (alen < sizeof(struct sockaddr_nl)) - return -EINVAL; - if ((nladdr->nl_groups || nladdr->nl_pid) && !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) return -EPERM; @@ -1182,7 +1728,8 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, nlk = nlk_sk(sk); if ((atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf || - test_bit(NETLINK_S_CONGESTED, &nlk->state))) { + test_bit(NETLINK_S_CONGESTED, &nlk->state)) && + !netlink_skb_is_mmaped(skb)) { DECLARE_WAITQUEUE(wait, current); if (!*timeo) { if (!ssk || netlink_is_kernel(ssk)) @@ -1220,7 +1767,14 @@ static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb) netlink_deliver_tap(skb); - skb_queue_tail(&sk->sk_receive_queue, skb); +#ifdef CONFIG_NETLINK_MMAP + if (netlink_skb_is_mmaped(skb)) + netlink_queue_mmaped_skb(sk, skb); + else if (netlink_rx_is_mmaped(sk)) + netlink_ring_set_copied(sk, skb); + else +#endif /* CONFIG_NETLINK_MMAP */ + skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_data_ready(sk); return len; } @@ -1244,6 +1798,9 @@ static struct sk_buff *netlink_trim(struct sk_buff *skb, gfp_t allocation) int delta; WARN_ON(skb->sk != NULL); + if (netlink_skb_is_mmaped(skb)) + return skb; + delta = skb->end - skb->tail; if (is_vmalloc_addr(skb->head) || delta * 2 < skb->truesize) return skb; @@ -1323,6 +1880,71 @@ struct sk_buff *__netlink_alloc_skb(struct sock *ssk, unsigned int size, unsigned int ldiff, u32 dst_portid, gfp_t gfp_mask) { +#ifdef CONFIG_NETLINK_MMAP + unsigned int maxlen, linear_size; + struct sock *sk = NULL; + struct sk_buff *skb; + struct netlink_ring *ring; + struct nl_mmap_hdr *hdr; + + sk = netlink_getsockbyportid(ssk, dst_portid); + if (IS_ERR(sk)) + goto out; + + ring = &nlk_sk(sk)->rx_ring; + /* fast-path without atomic ops for common case: non-mmaped receiver */ + if (ring->pg_vec == NULL) + goto out_put; + + /* We need to account the full linear size needed as a ring + * slot cannot have non-linear parts. + */ + linear_size = size + ldiff; + if (ring->frame_size - NL_MMAP_HDRLEN < linear_size) + goto out_put; + + skb = alloc_skb_head(gfp_mask); + if (skb == NULL) + goto err1; + + spin_lock_bh(&sk->sk_receive_queue.lock); + /* check again under lock */ + if (ring->pg_vec == NULL) + goto out_free; + + /* check again under lock */ + maxlen = ring->frame_size - NL_MMAP_HDRLEN; + if (maxlen < linear_size) + goto out_free; + + netlink_forward_ring(ring); + hdr = netlink_current_frame(ring, NL_MMAP_STATUS_UNUSED); + if (hdr == NULL) + goto err2; + + netlink_ring_setup_skb(skb, sk, ring, hdr); + netlink_set_status(hdr, NL_MMAP_STATUS_RESERVED); + atomic_inc(&ring->pending); + netlink_increment_head(ring); + + spin_unlock_bh(&sk->sk_receive_queue.lock); + return skb; + +err2: + kfree_skb(skb); + spin_unlock_bh(&sk->sk_receive_queue.lock); + netlink_overrun(sk); +err1: + sock_put(sk); + return NULL; + +out_free: + kfree_skb(skb); + spin_unlock_bh(&sk->sk_receive_queue.lock); +out_put: + sock_put(sk); +out: +#endif return alloc_skb(size, gfp_mask); } EXPORT_SYMBOL_GPL(__netlink_alloc_skb); @@ -1603,7 +2225,8 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, if (level != SOL_NETLINK) return -ENOPROTOOPT; - if (optlen >= sizeof(int) && + if (optname != NETLINK_RX_RING && optname != NETLINK_TX_RING && + optlen >= sizeof(int) && get_user(val, (unsigned int __user *)optval)) return -EFAULT; @@ -1656,6 +2279,25 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, } err = 0; break; +#ifdef CONFIG_NETLINK_MMAP + case NETLINK_RX_RING: + case NETLINK_TX_RING: { + struct nl_mmap_req req; + + /* Rings might consume more memory than queue limits, require + * CAP_NET_ADMIN. + */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (optlen < sizeof(req)) + return -EINVAL; + if (copy_from_user(&req, optval, sizeof(req))) + return -EFAULT; + err = netlink_set_ring(sk, &req, + optname == NETLINK_TX_RING); + break; + } +#endif /* CONFIG_NETLINK_MMAP */ case NETLINK_LISTEN_ALL_NSID: if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_BROADCAST)) return -EPERM; @@ -1802,8 +2444,6 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) if (msg->msg_namelen) { err = -EINVAL; - if (msg->msg_namelen < sizeof(struct sockaddr_nl)) - goto out; if (addr->nl_family != AF_NETLINK) goto out; dst_portid = addr->nl_pid; @@ -1827,6 +2467,18 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) smp_rmb(); } + /* It's a really convoluted way for userland to ask for mmaped + * sendmsg(), but that's what we've got... + */ + if (netlink_tx_is_mmaped(sk) && + iter_is_iovec(&msg->msg_iter) && + msg->msg_iter.nr_segs == 1 && + msg->msg_iter.iov->iov_base == NULL) { + err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, + &scm); + goto out; + } + err = -EMSGSIZE; if (len > sk->sk_sndbuf - 32) goto out; @@ -1905,7 +2557,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, /* Record the max length of recvmsg() calls for future allocations */ nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len); nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len, - SKB_WITH_OVERHEAD(32768)); + 16384); copied = data_skb->len; if (len < copied) { @@ -2133,7 +2785,7 @@ static int netlink_dump(struct sock *sk) struct sk_buff *skb = NULL; struct nlmsghdr *nlh; struct module *module; - int err = -ENOBUFS; + int len, err = -ENOBUFS; int alloc_min_size; int alloc_size; @@ -2143,7 +2795,8 @@ static int netlink_dump(struct sock *sk) goto errout_skb; } - if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) + if (!netlink_rx_is_mmaped(sk) && + atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) goto errout_skb; /* NLMSG_GOODSIZE is small to avoid high order allocations being @@ -2157,8 +2810,9 @@ static int netlink_dump(struct sock *sk) if (alloc_min_size < nlk->max_recvmsg_len) { alloc_size = nlk->max_recvmsg_len; skb = netlink_alloc_skb(sk, alloc_size, nlk->portid, - (GFP_KERNEL & ~__GFP_DIRECT_RECLAIM) | - __GFP_NOWARN | __GFP_NORETRY); + GFP_KERNEL | + __GFP_NOWARN | + __GFP_NORETRY); } if (!skb) { alloc_size = alloc_min_size; @@ -2181,11 +2835,9 @@ static int netlink_dump(struct sock *sk) skb_reserve(skb, skb_tailroom(skb) - alloc_size); netlink_skb_set_owner_r(skb, sk); - if (nlk->dump_done_errno > 0) - nlk->dump_done_errno = cb->dump(skb, cb); + len = cb->dump(skb, cb); - if (nlk->dump_done_errno > 0 || - skb_tailroom(skb) < nlmsg_total_size(sizeof(nlk->dump_done_errno))) { + if (len > 0) { mutex_unlock(nlk->cb_mutex); if (sk_filter(sk, skb)) @@ -2195,15 +2847,13 @@ static int netlink_dump(struct sock *sk) return 0; } - nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, - sizeof(nlk->dump_done_errno), NLM_F_MULTI); - if (WARN_ON(!nlh)) + nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI); + if (!nlh) goto errout_skb; nl_dump_check_consistent(cb, nlh); - memcpy(nlmsg_data(nlh), &nlk->dump_done_errno, - sizeof(nlk->dump_done_errno)); + memcpy(nlmsg_data(nlh), &len, sizeof(len)); if (sk_filter(sk, skb)) kfree_skb(skb); @@ -2236,7 +2886,16 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, struct netlink_sock *nlk; int ret; - atomic_inc(&skb->users); + /* Memory mapped dump requests need to be copied to avoid looping + * on the pending state in netlink_mmap_sendmsg() while the CB hold + * a reference to the skb. + */ + if (netlink_skb_is_mmaped(skb)) { + skb = skb_copy(skb, GFP_KERNEL); + if (skb == NULL) + return -ENOBUFS; + } else + atomic_inc(&skb->users); sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).portid); if (sk == NULL) { @@ -2259,7 +2918,6 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, cb = &nlk->cb; memset(cb, 0, sizeof(*cb)); - cb->start = control->start; cb->dump = control->dump; cb->done = control->done; cb->nlh = nlh; @@ -2269,13 +2927,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, cb->skb = skb; nlk->cb_running = true; - nlk->dump_done_errno = INT_MAX; mutex_unlock(nlk->cb_mutex); - if (cb->start) - cb->start(cb); - ret = netlink_dump(sk); sock_put(sk); @@ -2585,7 +3239,7 @@ static const struct proto_ops netlink_ops = { .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = netlink_getname, - .poll = datagram_poll, + .poll = netlink_poll, .ioctl = sock_no_ioctl, .listen = sock_no_listen, .shutdown = sock_no_shutdown, @@ -2593,7 +3247,7 @@ static const struct proto_ops netlink_ops = { .getsockopt = netlink_getsockopt, .sendmsg = netlink_sendmsg, .recvmsg = netlink_recvmsg, - .mmap = sock_no_mmap, + .mmap = netlink_mmap, .sendpage = sock_no_sendpage, }; diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index d987696c0eb4..14437d9b1965 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h @@ -3,7 +3,6 @@ #include #include -#include #include #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) @@ -38,7 +37,6 @@ struct netlink_sock { wait_queue_head_t wait; bool bound; bool cb_running; - int dump_done_errno; struct netlink_callback cb; struct mutex *cb_mutex; struct mutex cb_def_mutex; @@ -46,10 +44,15 @@ struct netlink_sock { int (*netlink_bind)(struct net *net, int group); void (*netlink_unbind)(struct net *net, int group); struct module *module; +#ifdef CONFIG_NETLINK_MMAP + struct mutex pg_vec_lock; + struct netlink_ring rx_ring; + struct netlink_ring tx_ring; + atomic_t mapped; +#endif /* CONFIG_NETLINK_MMAP */ struct rhash_head node; struct rcu_head rcu; - struct work_struct work; }; static inline struct netlink_sock *nlk_sk(struct sock *sk) @@ -57,6 +60,15 @@ static inline struct netlink_sock *nlk_sk(struct sock *sk) return container_of(sk, struct netlink_sock, sk); } +static inline bool netlink_skb_is_mmaped(const struct sk_buff *skb) +{ +#ifdef CONFIG_NETLINK_MMAP + return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED; +#else + return false; +#endif /* CONFIG_NETLINK_MMAP */ +} + struct netlink_table { struct rhashtable hash; struct hlist_head mc_list; diff --git a/net/netlink/diag.c b/net/netlink/diag.c index 8dd836a8dd60..3ee63a3cff30 100644 --- a/net/netlink/diag.c +++ b/net/netlink/diag.c @@ -8,6 +8,41 @@ #include "af_netlink.h" +#ifdef CONFIG_NETLINK_MMAP +static int sk_diag_put_ring(struct netlink_ring *ring, int nl_type, + struct sk_buff *nlskb) +{ + struct netlink_diag_ring ndr; + + ndr.ndr_block_size = ring->pg_vec_pages << PAGE_SHIFT; + ndr.ndr_block_nr = ring->pg_vec_len; + ndr.ndr_frame_size = ring->frame_size; + ndr.ndr_frame_nr = ring->frame_max + 1; + + return nla_put(nlskb, nl_type, sizeof(ndr), &ndr); +} + +static int sk_diag_put_rings_cfg(struct sock *sk, struct sk_buff *nlskb) +{ + struct netlink_sock *nlk = nlk_sk(sk); + int ret; + + mutex_lock(&nlk->pg_vec_lock); + ret = sk_diag_put_ring(&nlk->rx_ring, NETLINK_DIAG_RX_RING, nlskb); + if (!ret) + ret = sk_diag_put_ring(&nlk->tx_ring, NETLINK_DIAG_TX_RING, + nlskb); + mutex_unlock(&nlk->pg_vec_lock); + + return ret; +} +#else +static int sk_diag_put_rings_cfg(struct sock *sk, struct sk_buff *nlskb) +{ + return 0; +} +#endif + static int sk_diag_dump_groups(struct sock *sk, struct sk_buff *nlskb) { struct netlink_sock *nlk = nlk_sk(sk); @@ -52,6 +87,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, sock_diag_put_meminfo(sk, skb, NETLINK_DIAG_MEMINFO)) goto out_nlmsg_trim; + if ((req->ndiag_show & NDIAG_SHOW_RING_CFG) && + sk_diag_put_rings_cfg(sk, skb)) + goto out_nlmsg_trim; + nlmsg_end(skb, nlh); return 0; diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index d681dbaf00c1..bc0e504f33a6 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -513,20 +513,6 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, } EXPORT_SYMBOL(genlmsg_put); -static int genl_lock_start(struct netlink_callback *cb) -{ - /* our ops are always const - netlink API doesn't propagate that */ - const struct genl_ops *ops = cb->data; - int rc = 0; - - if (ops->start) { - genl_lock(); - rc = ops->start(cb); - genl_unlock(); - } - return rc; -} - static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb) { /* our ops are always const - netlink API doesn't propagate that */ @@ -591,7 +577,6 @@ static int genl_family_rcv_msg(struct genl_family *family, .module = family->module, /* we have const, but the netlink API doesn't */ .data = (void *)ops, - .start = genl_lock_start, .dump = genl_lock_dumpit, .done = genl_lock_done, }; @@ -603,7 +588,6 @@ static int genl_family_rcv_msg(struct genl_family *family, } else { struct netlink_dump_control c = { .module = family->module, - .start = ops->start, .dump = ops->dumpit, .done = ops->done, }; @@ -1118,7 +1102,6 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group, { struct sk_buff *tmp; struct net *net, *prev = NULL; - bool delivered = false; int err; for_each_net_rcu(net) { @@ -1130,21 +1113,14 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group, } err = nlmsg_multicast(prev->genl_sock, tmp, portid, group, flags); - if (!err) - delivered = true; - else if (err != -ESRCH) + if (err) goto error; } prev = net; } - err = nlmsg_multicast(prev->genl_sock, skb, portid, group, flags); - if (!err) - delivered = true; - else if (err != -ESRCH) - return err; - return delivered ? 0 : -ESRCH; + return nlmsg_multicast(prev->genl_sock, skb, portid, group, flags); error: kfree_skb(skb); return err; diff --git a/net/nfc/core.c b/net/nfc/core.c index 1471e4b0aa2c..1fe3d3b362c0 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -969,8 +969,6 @@ static void nfc_release(struct device *d) kfree(se); } - ida_simple_remove(&nfc_index_ida, dev->idx); - kfree(dev); } @@ -1045,7 +1043,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, int tx_headroom, int tx_tailroom) { struct nfc_dev *dev; - int rc; if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || !ops->deactivate_target || !ops->im_transceive) @@ -1058,15 +1055,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, if (!dev) return NULL; - rc = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL); - if (rc < 0) - goto err_free_dev; - dev->idx = rc; - - dev->dev.class = &nfc_class; - dev_set_name(&dev->dev, "nfc%d", dev->idx); - device_initialize(&dev->dev); - dev->ops = ops; dev->supported_protocols = supported_protocols; dev->tx_headroom = tx_headroom; @@ -1089,11 +1077,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, } return dev; - -err_free_dev: - kfree(dev); - - return NULL; } EXPORT_SYMBOL(nfc_allocate_device); @@ -1108,6 +1091,14 @@ int nfc_register_device(struct nfc_dev *dev) pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + dev->idx = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL); + if (dev->idx < 0) + return dev->idx; + + dev->dev.class = &nfc_class; + dev_set_name(&dev->dev, "nfc%d", dev->idx); + device_initialize(&dev->dev); + mutex_lock(&nfc_devlist_mutex); nfc_devlist_generation++; rc = device_add(&dev->dev); @@ -1145,10 +1136,12 @@ EXPORT_SYMBOL(nfc_register_device); */ void nfc_unregister_device(struct nfc_dev *dev) { - int rc; + int rc, id; pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + id = dev->idx; + if (dev->rfkill) { rfkill_unregister(dev->rfkill); rfkill_destroy(dev->rfkill); @@ -1173,6 +1166,8 @@ void nfc_unregister_device(struct nfc_dev *dev) nfc_devlist_generation++; device_del(&dev->dev); mutex_unlock(&nfc_devlist_mutex); + + ida_simple_remove(&nfc_index_ida, id); } EXPORT_SYMBOL(nfc_unregister_device); diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c index 04f060488686..3621a902cb6e 100644 --- a/net/nfc/llcp_commands.c +++ b/net/nfc/llcp_commands.c @@ -149,10 +149,6 @@ struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri, pr_debug("uri: %s, len: %zu\n", uri, uri_len); - /* sdreq->tlv_len is u8, takes uri_len, + 3 for header, + 1 for NULL */ - if (WARN_ON_ONCE(uri_len > U8_MAX - 4)) - return NULL; - sdreq = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL); if (sdreq == NULL) return NULL; @@ -754,14 +750,11 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, pr_debug("Fragment %zd bytes remaining %zd", frag_len, remaining_len); - pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, 0, + pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT, frag_len + LLCP_HEADER_SIZE, &err); if (pdu == NULL) { - pr_err("Could not allocate PDU (error=%d)\n", err); - len -= remaining_len; - if (len == 0) - len = err; - break; + pr_err("Could not allocate PDU\n"); + continue; } pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI); diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 9c222a106c7f..ecf0a0196f18 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -76,8 +76,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) struct sockaddr_nfc_llcp llcp_addr; int len, ret = 0; - if (!addr || alen < offsetofend(struct sockaddr, sa_family) || - addr->sa_family != AF_NFC) + if (!addr || addr->sa_family != AF_NFC) return -EINVAL; pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family); @@ -151,8 +150,7 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr, struct sockaddr_nfc_llcp llcp_addr; int len, ret = 0; - if (!addr || alen < offsetofend(struct sockaddr, sa_family) || - addr->sa_family != AF_NFC) + if (!addr || addr->sa_family != AF_NFC) return -EINVAL; pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family); @@ -657,7 +655,8 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags); - if (!addr || len < sizeof(*addr) || addr->sa_family != AF_NFC) + if (!addr || len < sizeof(struct sockaddr_nfc) || + addr->sa_family != AF_NFC) return -EINVAL; if (addr->service_name_len == 0 && addr->dsap == 0) diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 67583ad7f610..10c99a578421 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -1084,7 +1084,8 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, return ndev; free_nfc: - nfc_free_device(ndev->nfc_dev); + kfree(ndev->nfc_dev); + free_nci: kfree(ndev); return NULL; diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 32cb0c87e852..f58c1fba1026 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -68,8 +68,7 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { }; static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { - [NFC_SDP_ATTR_URI] = { .type = NLA_STRING, - .len = U8_MAX - 4 }, + [NFC_SDP_ATTR_URI] = { .type = NLA_STRING }, [NFC_SDP_ATTR_SAP] = { .type = NLA_U8 }, }; @@ -874,9 +873,7 @@ static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info) u32 device_idx, target_idx, protocol; int rc; - if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || - !info->attrs[NFC_ATTR_TARGET_INDEX] || - !info->attrs[NFC_ATTR_PROTOCOLS]) + if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) return -EINVAL; device_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 1829adb23505..e004067ec24a 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -361,38 +361,10 @@ ovs_ct_expect_find(struct net *net, const struct nf_conntrack_zone *zone, u16 proto, const struct sk_buff *skb) { struct nf_conntrack_tuple tuple; - struct nf_conntrack_expect *exp; if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, net, &tuple)) return NULL; - - exp = __nf_ct_expect_find(net, zone, &tuple); - if (exp) { - struct nf_conntrack_tuple_hash *h; - - /* Delete existing conntrack entry, if it clashes with the - * expectation. This can happen since conntrack ALGs do not - * check for clashes between (new) expectations and existing - * conntrack entries. nf_conntrack_in() will check the - * expectations only if a conntrack entry can not be found, - * which can lead to OVS finding the expectation (here) in the - * init direction, but which will not be removed by the - * nf_conntrack_in() call, if a matching conntrack entry is - * found instead. In this case all init direction packets - * would be reported as new related packets, while reply - * direction packets would be reported as un-related - * established packets. - */ - h = nf_conntrack_find_get(net, zone, &tuple); - if (h) { - struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); - - nf_ct_delete(ct, 0, 0); - nf_conntrack_put(&ct->ct_general); - } - } - - return exp; + return __nf_ct_expect_find(net, zone, &tuple); } /* Determine whether skb->nfct is equal to the result of conntrack lookup. */ @@ -529,7 +501,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb, /* The conntrack module expects to be working at L3. */ nh_ofs = skb_network_offset(skb); - skb_pull_rcsum(skb, nh_ofs); + skb_pull(skb, nh_ofs); if (key->ip.frag != OVS_FRAG_TYPE_NONE) { err = handle_fragments(net, key, info->zone.id, skb); @@ -555,7 +527,6 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb, &info->labels.mask); err: skb_push(skb, nh_ofs); - skb_postpush_rcsum(skb, skb->data, nh_ofs); if (err) kfree_skb(skb); return err; @@ -605,8 +576,8 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, nla_for_each_nested(a, attr, rem) { int type = nla_type(a); - int maxlen; - int minlen; + int maxlen = ovs_ct_attr_lens[type].maxlen; + int minlen = ovs_ct_attr_lens[type].minlen; if (type > OVS_CT_ATTR_MAX) { OVS_NLERR(log, @@ -614,9 +585,6 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, type, OVS_CT_ATTR_MAX); return -EINVAL; } - - maxlen = ovs_ct_attr_lens[type].maxlen; - minlen = ovs_ct_attr_lens[type].minlen; if (nla_len(a) < minlen || nla_len(a) > maxlen) { OVS_NLERR(log, "Conntrack attr type has unexpected length (type=%d, length=%d, expected=%d)", diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 624c4719e404..d1bd4a45ca2d 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c @@ -588,7 +588,7 @@ static int ip_tun_from_nlattr(const struct nlattr *attr, ipv4 = true; break; case OVS_TUNNEL_KEY_ATTR_IPV6_SRC: - SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.src, + SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.dst, nla_get_in6_addr(a), is_mask); ipv6 = true; break; @@ -1141,10 +1141,13 @@ static void nlattr_set(struct nlattr *attr, u8 val, /* The nlattr stream should already have been validated */ nla_for_each_nested(nla, attr, rem) { - if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED) - nlattr_set(nla, val, tbl[nla_type(nla)].next ? : tbl); - else + if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED) { + if (tbl[nla_type(nla)].next) + tbl = tbl[nla_type(nla)].next; + nlattr_set(nla, val, tbl); + } else { memset(nla_data(nla), val, nla_len(nla)); + } if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE) *(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK; @@ -1669,11 +1672,14 @@ int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb) #define MAX_ACTIONS_BUFSIZE (32 * 1024) -static struct sw_flow_actions *nla_alloc_flow_actions(int size) +static struct sw_flow_actions *nla_alloc_flow_actions(int size, bool log) { struct sw_flow_actions *sfa; - WARN_ON_ONCE(size > MAX_ACTIONS_BUFSIZE); + if (size > MAX_ACTIONS_BUFSIZE) { + OVS_NLERR(log, "Flow action size %u bytes exceeds max", size); + return ERR_PTR(-EINVAL); + } sfa = kmalloc(sizeof(*sfa) + size, GFP_KERNEL); if (!sfa) @@ -1746,15 +1752,12 @@ static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa, new_acts_size = ksize(*sfa) * 2; if (new_acts_size > MAX_ACTIONS_BUFSIZE) { - if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) { - OVS_NLERR(log, "Flow action size exceeds max %u", - MAX_ACTIONS_BUFSIZE); + if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) return ERR_PTR(-EMSGSIZE); - } new_acts_size = MAX_ACTIONS_BUFSIZE; } - acts = nla_alloc_flow_actions(new_acts_size); + acts = nla_alloc_flow_actions(new_acts_size, log); if (IS_ERR(acts)) return (void *)acts; @@ -2366,7 +2369,7 @@ int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, { int err; - *sfa = nla_alloc_flow_actions(min(nla_len(attr), MAX_ACTIONS_BUFSIZE)); + *sfa = nla_alloc_flow_actions(nla_len(attr), log); if (IS_ERR(*sfa)) return PTR_ERR(*sfa); diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index 5eb7694348b5..d933cb89efac 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c @@ -91,8 +91,6 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms) struct vxlan_config conf = { .no_share = true, .flags = VXLAN_F_COLLECT_METADATA | VXLAN_F_UDP_ZERO_CSUM6_RX, - /* Don't restrict the packets that can be sent by MTU */ - .mtu = IP_MAX_MTU, }; if (!options) { diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 5ecbc77acf90..dd5e8dd84a70 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -249,7 +249,7 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po); static int packet_direct_xmit(struct sk_buff *skb) { struct net_device *dev = skb->dev; - struct sk_buff *orig_skb = skb; + netdev_features_t features; struct netdev_queue *txq; int ret = NETDEV_TX_BUSY; @@ -257,8 +257,9 @@ static int packet_direct_xmit(struct sk_buff *skb) !netif_carrier_ok(dev))) goto drop; - skb = validate_xmit_skb_list(skb, dev); - if (skb != orig_skb) + features = netif_skb_features(skb); + if (skb_needs_linearize(skb, features) && + __skb_linearize(skb)) goto drop; txq = skb_get_tx_queue(dev, skb); @@ -278,7 +279,7 @@ static int packet_direct_xmit(struct sk_buff *skb) return ret; drop: atomic_long_inc(&dev->tx_dropped); - kfree_skb_list(skb); + kfree_skb(skb); return NET_XMIT_DROP; } @@ -332,11 +333,11 @@ static void packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb) skb_set_queue_mapping(skb, queue_index); } -/* __register_prot_hook must be invoked through register_prot_hook +/* register_prot_hook must be invoked with the po->bind_lock held, * or from a context in which asynchronous accesses to the packet * socket is not possible (packet_create()). */ -static void __register_prot_hook(struct sock *sk) +static void register_prot_hook(struct sock *sk) { struct packet_sock *po = pkt_sk(sk); @@ -351,13 +352,8 @@ static void __register_prot_hook(struct sock *sk) } } -static void register_prot_hook(struct sock *sk) -{ - lockdep_assert_held_once(&pkt_sk(sk)->bind_lock); - __register_prot_hook(sk); -} - -/* If the sync parameter is true, we will temporarily drop +/* {,__}unregister_prot_hook() must be invoked with the po->bind_lock + * held. If the sync parameter is true, we will temporarily drop * the po->bind_lock and do a synchronize_net to make sure no * asynchronous packet processing paths still refer to the elements * of po->prot_hook. If the sync parameter is false, it is the @@ -367,8 +363,6 @@ static void __unregister_prot_hook(struct sock *sk, bool sync) { struct packet_sock *po = pkt_sk(sk); - lockdep_assert_held_once(&po->bind_lock); - po->running = 0; if (po->fanout) @@ -1347,7 +1341,7 @@ static unsigned int fanout_demux_hash(struct packet_fanout *f, struct sk_buff *skb, unsigned int num) { - return reciprocal_scale(__skb_get_hash_symmetric(skb), num); + return reciprocal_scale(skb_get_hash(skb), num); } static unsigned int fanout_demux_lb(struct packet_fanout *f, @@ -1504,8 +1498,6 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po) f->arr[f->num_members] = sk; smp_wmb(); f->num_members++; - if (f->num_members == 1) - dev_add_pack(&f->prot_hook); spin_unlock(&f->lock); } @@ -1522,8 +1514,6 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po) BUG_ON(i >= f->num_members); f->arr[i] = f->arr[f->num_members - 1]; f->num_members--; - if (f->num_members == 0) - __dev_remove_pack(&f->prot_hook); spin_unlock(&f->lock); } @@ -1658,6 +1648,10 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) } mutex_lock(&fanout_mutex); + + err = -EINVAL; + if (!po->running) + goto out; err = -EALREADY; if (po->fanout) @@ -1705,45 +1699,32 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) match->prot_hook.func = packet_rcv_fanout; match->prot_hook.af_packet_priv = match; match->prot_hook.id_match = match_fanout_group; + dev_add_pack(&match->prot_hook); list_add(&match->list, &fanout_list); } err = -EINVAL; - - spin_lock(&po->bind_lock); - if (po->running && - match->type == type && + if (match->type == type && match->prot_hook.type == po->prot_hook.type && match->prot_hook.dev == po->prot_hook.dev) { err = -ENOSPC; if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) { __dev_remove_pack(&po->prot_hook); po->fanout = match; - po->rollover = rollover; - rollover = NULL; atomic_inc(&match->sk_ref); __fanout_link(sk, po); err = 0; } } - spin_unlock(&po->bind_lock); - - if (err && !atomic_read(&match->sk_ref)) { - list_del(&match->list); - kfree(match); - } - out: - kfree(rollover); + if (err && rollover) { + kfree(rollover); + po->rollover = NULL; + } mutex_unlock(&fanout_mutex); return err; } -/* If pkt_sk(sk)->fanout->sk_ref is zero, this function removes - * pkt_sk(sk)->fanout from fanout_list and returns pkt_sk(sk)->fanout. - * It is the responsibility of the caller to call fanout_release_data() and - * free the returned packet_fanout (after synchronize_net()) - */ -static struct packet_fanout *fanout_release(struct sock *sk) +static void fanout_release(struct sock *sk) { struct packet_sock *po = pkt_sk(sk); struct packet_fanout *f; @@ -1753,14 +1734,18 @@ static struct packet_fanout *fanout_release(struct sock *sk) if (f) { po->fanout = NULL; - if (atomic_dec_and_test(&f->sk_ref)) + if (atomic_dec_and_test(&f->sk_ref)) { list_del(&f->list); - else - f = NULL; + dev_remove_pack(&f->prot_hook); + fanout_release_data(f); + kfree(f); + } + + + if (po->rollover) + kfree_rcu(po->rollover, rcu); } mutex_unlock(&fanout_mutex); - - return f; } static bool packet_extra_vlan_len_allowed(const struct net_device *dev, @@ -2660,8 +2645,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) int vnet_hdr_len; struct packet_sock *po = pkt_sk(sk); unsigned short gso_type = 0; - bool has_vnet_hdr = false; - int hlen, tlen, linear; + int hlen, tlen; int extra_len = 0; ssize_t n; @@ -2748,7 +2732,6 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) goto out_unlock; } - has_vnet_hdr = true; } if (unlikely(sock_flag(sk, SOCK_NOFCS))) { @@ -2766,24 +2749,19 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) err = -ENOBUFS; hlen = LL_RESERVED_SPACE(dev); tlen = dev->needed_tailroom; - linear = __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len); - linear = max(linear, min_t(int, len, dev->hard_header_len)); - skb = packet_alloc_skb(sk, hlen + tlen, hlen, len, linear, + skb = packet_alloc_skb(sk, hlen + tlen, hlen, len, + __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len), msg->msg_flags & MSG_DONTWAIT, &err); if (skb == NULL) goto out_unlock; - skb_reset_network_header(skb); + skb_set_network_header(skb, reserve); err = -EINVAL; if (sock->type == SOCK_DGRAM) { offset = dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len); if (unlikely(offset < 0)) goto out_free; - } else if (reserve) { - skb_reserve(skb, -reserve); - if (len < reserve) - skb_reset_network_header(skb); } /* Returns -EFAULT on error */ @@ -2812,7 +2790,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) packet_pick_tx_queue(dev, skb); - if (has_vnet_hdr) { + if (po->has_vnet_hdr) { if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { u16 s = __virtio16_to_cpu(vio_le(), vnet_hdr.csum_start); u16 o = __virtio16_to_cpu(vio_le(), vnet_hdr.csum_offset); @@ -2875,7 +2853,6 @@ static int packet_release(struct socket *sock) { struct sock *sk = sock->sk; struct packet_sock *po; - struct packet_fanout *f; struct net *net; union tpacket_req_u req_u; @@ -2905,7 +2882,6 @@ static int packet_release(struct socket *sock) packet_flush_mclist(sk); - lock_sock(sk); if (po->rx_ring.pg_vec) { memset(&req_u, 0, sizeof(req_u)); packet_set_ring(sk, &req_u, 1, 0); @@ -2915,17 +2891,10 @@ static int packet_release(struct socket *sock) memset(&req_u, 0, sizeof(req_u)); packet_set_ring(sk, &req_u, 1, 1); } - release_sock(sk); - f = fanout_release(sk); + fanout_release(sk); synchronize_net(); - - if (f) { - kfree(po->rollover); - fanout_release_data(f); - kfree(f); - } /* * Now the socket is dead. No more input will appear. */ @@ -2991,10 +2960,6 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex, if (need_rehook) { if (po->running) { rcu_read_unlock(); - /* prevents packet_notifier() from calling - * register_prot_hook() - */ - po->num = 0; __unregister_prot_hook(sk, true); rcu_read_lock(); dev_curr = po->prot_hook.dev; @@ -3003,7 +2968,6 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex, dev->ifindex); } - BUG_ON(po->running); po->num = proto; po->prot_hook.type = proto; @@ -3047,7 +3011,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; - char name[sizeof(uaddr->sa_data) + 1]; + char name[15]; /* * Check legality @@ -3055,11 +3019,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, if (addr_len != sizeof(struct sockaddr)) return -EINVAL; - /* uaddr->sa_data comes from the userspace, it's not guaranteed to be - * zero-terminated. - */ - memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data)); - name[sizeof(uaddr->sa_data)] = 0; + strlcpy(name, uaddr->sa_data, sizeof(name)); return packet_do_bind(sk, name, 0, pkt_sk(sk)->num); } @@ -3149,7 +3109,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, if (proto) { po->prot_hook.type = proto; - __register_prot_hook(sk); + register_prot_hook(sk); } mutex_lock(&net->packet.sklist_lock); @@ -3585,7 +3545,6 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv union tpacket_req_u req_u; int len; - lock_sock(sk); switch (po->tp_version) { case TPACKET_V1: case TPACKET_V2: @@ -3596,21 +3555,14 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv len = sizeof(req_u.req3); break; } - if (optlen < len) { - ret = -EINVAL; - } else { - if (pkt_sk(sk)->has_vnet_hdr) { - ret = -EINVAL; - } else { - if (copy_from_user(&req_u.req, optval, len)) - ret = -EFAULT; - else - ret = packet_set_ring(sk, &req_u, 0, - optname == PACKET_TX_RING); - } - } - release_sock(sk); - return ret; + if (optlen < len) + return -EINVAL; + if (pkt_sk(sk)->has_vnet_hdr) + return -EINVAL; + if (copy_from_user(&req_u.req, optval, len)) + return -EFAULT; + return packet_set_ring(sk, &req_u, 0, + optname == PACKET_TX_RING); } case PACKET_COPY_THRESH: { @@ -3658,8 +3610,6 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv return -EINVAL; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; - if (val > INT_MAX) - return -EINVAL; lock_sock(sk); if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { ret = -EBUSY; @@ -3676,18 +3626,12 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (optlen != sizeof(val)) return -EINVAL; + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) + return -EBUSY; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; - - lock_sock(sk); - if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { - ret = -EBUSY; - } else { - po->tp_loss = !!val; - ret = 0; - } - release_sock(sk); - return ret; + po->tp_loss = !!val; + return 0; } case PACKET_AUXDATA: { @@ -3698,9 +3642,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; - lock_sock(sk); po->auxdata = !!val; - release_sock(sk); return 0; } case PACKET_ORIGDEV: @@ -3712,9 +3654,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; - lock_sock(sk); po->origdev = !!val; - release_sock(sk); return 0; } case PACKET_VNET_HDR: @@ -3723,20 +3663,15 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (sock->type != SOCK_RAW) return -EINVAL; + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) + return -EBUSY; if (optlen < sizeof(val)) return -EINVAL; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; - lock_sock(sk); - if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { - ret = -EBUSY; - } else { - po->has_vnet_hdr = !!val; - ret = 0; - } - release_sock(sk); - return ret; + po->has_vnet_hdr = !!val; + return 0; } case PACKET_TIMESTAMP: { @@ -3774,17 +3709,11 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (optlen != sizeof(val)) return -EINVAL; + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) + return -EBUSY; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; - - lock_sock(sk); - if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { - ret = -EBUSY; - } else { - po->tp_tx_has_off = !!val; - ret = 0; - } - release_sock(sk); + po->tp_tx_has_off = !!val; return 0; } case PACKET_QDISC_BYPASS: @@ -3857,8 +3786,6 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, case PACKET_HDRLEN: if (len > sizeof(int)) len = sizeof(int); - if (len < sizeof(int)) - return -EINVAL; if (copy_from_user(&val, optval, len)) return -EFAULT; switch (val) { @@ -4179,8 +4106,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, } if (req->tp_block_nr) { - unsigned int min_frame_size; - /* Sanity tests and some calculations */ err = -EBUSY; if (unlikely(rb->pg_vec)) @@ -4203,12 +4128,12 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, goto out; if (unlikely(!PAGE_ALIGNED(req->tp_block_size))) goto out; - min_frame_size = po->tp_hdrlen + po->tp_reserve; if (po->tp_version >= TPACKET_V3 && - req->tp_block_size < - BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv) + min_frame_size) + req->tp_block_size <= + BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv)) goto out; - if (unlikely(req->tp_frame_size < min_frame_size)) + if (unlikely(req->tp_frame_size < po->tp_hdrlen + + po->tp_reserve)) goto out; if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1))) goto out; @@ -4216,8 +4141,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, rb->frames_per_block = req->tp_block_size / req->tp_frame_size; if (unlikely(rb->frames_per_block == 0)) goto out; - if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr)) - goto out; if (unlikely((rb->frames_per_block * req->tp_block_nr) != req->tp_frame_nr)) goto out; @@ -4289,7 +4212,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, register_prot_hook(sk); } spin_unlock(&po->bind_lock); - if (pg_vec && (po->tp_version > TPACKET_V2)) { + if (closing && (po->tp_version > TPACKET_V2)) { /* Because we don't support block-based V3 on tx-ring */ if (!tx_ring) prb_shutdown_retire_blk_timer(po, rb_queue); diff --git a/net/packet/internal.h b/net/packet/internal.h index 1309e2a7baad..9ee46314b7d7 100644 --- a/net/packet/internal.h +++ b/net/packet/internal.h @@ -92,6 +92,7 @@ struct packet_fanout { struct packet_rollover { int sock; + struct rcu_head rcu; atomic_long_t num; atomic_long_t num_huge; atomic_long_t num_failed; @@ -109,12 +110,10 @@ struct packet_sock { int copy_thresh; spinlock_t bind_lock; struct mutex pg_vec_lock; - unsigned int running; /* bind_lock must be held */ - unsigned int auxdata:1, /* writer must hold sock lock */ + unsigned int running:1, /* prot_hook is attached*/ + auxdata:1, origdev:1, - has_vnet_hdr:1, - tp_loss:1, - tp_tx_has_off:1; + has_vnet_hdr:1; int pressure; int ifindex; /* bound device */ __be16 num; @@ -124,6 +123,8 @@ struct packet_sock { enum tpacket_versions tp_version; unsigned int tp_hdrlen; unsigned int tp_reserve; + unsigned int tp_loss:1; + unsigned int tp_tx_has_off:1; unsigned int tp_tstamp; struct net_device __rcu *cached_dev; int (*xmit)(struct sk_buff *skb); diff --git a/net/rds/bind.c b/net/rds/bind.c index e29b47193645..b22ea956522b 100644 --- a/net/rds/bind.c +++ b/net/rds/bind.c @@ -108,7 +108,6 @@ static int rds_add_bound(struct rds_sock *rs, __be32 addr, __be16 *port) rs, &addr, (int)ntohs(*port)); break; } else { - rs->rs_bound_addr = 0; rds_sock_put(rs); ret = -ENOMEM; break; diff --git a/net/rds/cong.c b/net/rds/cong.c index 6641bcf7c185..e6144b8246fd 100644 --- a/net/rds/cong.c +++ b/net/rds/cong.c @@ -299,7 +299,7 @@ void rds_cong_set_bit(struct rds_cong_map *map, __be16 port) i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; - set_bit_le(off, (void *)map->m_page_addrs[i]); + __set_bit_le(off, (void *)map->m_page_addrs[i]); } void rds_cong_clear_bit(struct rds_cong_map *map, __be16 port) @@ -313,7 +313,7 @@ void rds_cong_clear_bit(struct rds_cong_map *map, __be16 port) i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; - clear_bit_le(off, (void *)map->m_page_addrs[i]); + __clear_bit_le(off, (void *)map->m_page_addrs[i]); } static int rds_cong_test_bit(struct rds_cong_map *map, __be16 port) diff --git a/net/rds/ib.c b/net/rds/ib.c index ed51ccc84b3a..f222885ac0c7 100644 --- a/net/rds/ib.c +++ b/net/rds/ib.c @@ -336,8 +336,7 @@ static int rds_ib_laddr_check(struct net *net, __be32 addr) /* Create a CMA ID and try to bind it. This catches both * IB and iWARP capable NICs. */ - cm_id = rdma_create_id(&init_net, rds_rdma_cm_event_handler, - NULL, RDMA_PS_TCP, IB_QPT_RC); + cm_id = rdma_create_id(&init_net, NULL, NULL, RDMA_PS_TCP, IB_QPT_RC); if (IS_ERR(cm_id)) return PTR_ERR(cm_id); diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index a6f5b3d21571..da5a7fb98c77 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c @@ -381,7 +381,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) ret = PTR_ERR(ic->i_send_cq); ic->i_send_cq = NULL; rdsdebug("ib_create_cq send failed: %d\n", ret); - goto rds_ibdev_out; + goto out; } cq_attr.cqe = ic->i_recv_ring.w_nr; @@ -392,19 +392,19 @@ static int rds_ib_setup_qp(struct rds_connection *conn) ret = PTR_ERR(ic->i_recv_cq); ic->i_recv_cq = NULL; rdsdebug("ib_create_cq recv failed: %d\n", ret); - goto send_cq_out; + goto out; } ret = ib_req_notify_cq(ic->i_send_cq, IB_CQ_NEXT_COMP); if (ret) { rdsdebug("ib_req_notify_cq send failed: %d\n", ret); - goto recv_cq_out; + goto out; } ret = ib_req_notify_cq(ic->i_recv_cq, IB_CQ_SOLICITED); if (ret) { rdsdebug("ib_req_notify_cq recv failed: %d\n", ret); - goto recv_cq_out; + goto out; } /* XXX negotiate max send/recv with remote? */ @@ -428,7 +428,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) ret = rdma_create_qp(ic->i_cm_id, ic->i_pd, &attr); if (ret) { rdsdebug("rdma_create_qp failed: %d\n", ret); - goto recv_cq_out; + goto out; } ic->i_send_hdrs = ib_dma_alloc_coherent(dev, @@ -438,7 +438,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) if (!ic->i_send_hdrs) { ret = -ENOMEM; rdsdebug("ib_dma_alloc_coherent send failed\n"); - goto qp_out; + goto out; } ic->i_recv_hdrs = ib_dma_alloc_coherent(dev, @@ -448,7 +448,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) if (!ic->i_recv_hdrs) { ret = -ENOMEM; rdsdebug("ib_dma_alloc_coherent recv failed\n"); - goto send_hdrs_dma_out; + goto out; } ic->i_ack = ib_dma_alloc_coherent(dev, sizeof(struct rds_header), @@ -456,7 +456,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) if (!ic->i_ack) { ret = -ENOMEM; rdsdebug("ib_dma_alloc_coherent ack failed\n"); - goto recv_hdrs_dma_out; + goto out; } ic->i_sends = vzalloc_node(ic->i_send_ring.w_nr * sizeof(struct rds_ib_send_work), @@ -464,7 +464,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) if (!ic->i_sends) { ret = -ENOMEM; rdsdebug("send allocation failed\n"); - goto ack_dma_out; + goto out; } ic->i_recvs = vzalloc_node(ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work), @@ -472,7 +472,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) if (!ic->i_recvs) { ret = -ENOMEM; rdsdebug("recv allocation failed\n"); - goto sends_out; + goto out; } rds_ib_recv_init_ack(ic); @@ -480,33 +480,8 @@ static int rds_ib_setup_qp(struct rds_connection *conn) rdsdebug("conn %p pd %p cq %p %p\n", conn, ic->i_pd, ic->i_send_cq, ic->i_recv_cq); - return ret; - -sends_out: - vfree(ic->i_sends); -ack_dma_out: - ib_dma_free_coherent(dev, sizeof(struct rds_header), - ic->i_ack, ic->i_ack_dma); -recv_hdrs_dma_out: - ib_dma_free_coherent(dev, ic->i_recv_ring.w_nr * - sizeof(struct rds_header), - ic->i_recv_hdrs, ic->i_recv_hdrs_dma); -send_hdrs_dma_out: - ib_dma_free_coherent(dev, ic->i_send_ring.w_nr * - sizeof(struct rds_header), - ic->i_send_hdrs, ic->i_send_hdrs_dma); -qp_out: - rdma_destroy_qp(ic->i_cm_id); -recv_cq_out: - if (!ib_destroy_cq(ic->i_recv_cq)) - ic->i_recv_cq = NULL; -send_cq_out: - if (!ib_destroy_cq(ic->i_send_cq)) - ic->i_send_cq = NULL; -rds_ibdev_out: - rds_ib_remove_conn(rds_ibdev, conn); +out: rds_ib_dev_put(rds_ibdev); - return ret; } diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index 094e2a12860a..eac30bf486d7 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c @@ -68,6 +68,16 @@ static void rds_ib_send_complete(struct rds_message *rm, complete(rm, notify_status); } +static void rds_ib_send_unmap_data(struct rds_ib_connection *ic, + struct rm_data_op *op, + int wc_status) +{ + if (op->op_nents) + ib_dma_unmap_sg(ic->i_cm_id->device, + op->op_sg, op->op_nents, + DMA_TO_DEVICE); +} + static void rds_ib_send_unmap_rdma(struct rds_ib_connection *ic, struct rm_rdma_op *op, int wc_status) @@ -128,21 +138,6 @@ static void rds_ib_send_unmap_atomic(struct rds_ib_connection *ic, rds_ib_stats_inc(s_ib_atomic_fadd); } -static void rds_ib_send_unmap_data(struct rds_ib_connection *ic, - struct rm_data_op *op, - int wc_status) -{ - struct rds_message *rm = container_of(op, struct rds_message, data); - - if (op->op_nents) - ib_dma_unmap_sg(ic->i_cm_id->device, - op->op_sg, op->op_nents, - DMA_TO_DEVICE); - - if (rm->rdma.op_active && rm->data.op_notify) - rds_ib_send_unmap_rdma(ic, &rm->rdma, wc_status); -} - /* * Unmap the resources associated with a struct send_work. * diff --git a/net/rds/loop.c b/net/rds/loop.c index 05cab8c5a379..6b12b68541ae 100644 --- a/net/rds/loop.c +++ b/net/rds/loop.c @@ -191,5 +191,4 @@ struct rds_transport rds_loop_transport = { .inc_copy_to_user = rds_message_inc_copy_to_user, .inc_free = rds_loop_inc_free, .t_name = "loopback", - .t_type = RDS_TRANS_LOOP, }; diff --git a/net/rds/rdma.c b/net/rds/rdma.c index bdfc395d1be2..4c93badeabf2 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -184,7 +184,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args, long i; int ret; - if (rs->rs_bound_addr == 0 || !rs->rs_transport) { + if (rs->rs_bound_addr == 0) { ret = -ENOTCONN; /* XXX not a great errno */ goto out; } @@ -517,9 +517,6 @@ int rds_rdma_extra_size(struct rds_rdma_args *args) local_vec = (struct rds_iovec __user *)(unsigned long) args->local_vec_addr; - if (args->nr_local == 0) - return -EINVAL; - /* figure out the number of pages in the vector */ for (i = 0; i < args->nr_local; i++) { if (copy_from_user(&vec, &local_vec[i], @@ -629,16 +626,6 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm, } op->op_notifier->n_user_token = args->user_token; op->op_notifier->n_status = RDS_RDMA_SUCCESS; - - /* Enable rmda notification on data operation for composite - * rds messages and make sure notification is enabled only - * for the data operation which follows it so that application - * gets notified only after full message gets delivered. - */ - if (rm->data.op_sg) { - rm->rdma.op_notify = 0; - rm->data.op_notify = !!(args->flags & RDS_RDMA_NOTIFY_ME); - } } /* The cookie contains the R_Key of the remote memory region, and @@ -869,7 +856,6 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm, err: if (page) put_page(page); - rm->atomic.op_active = 0; kfree(rm->atomic.op_notifier); return ret; diff --git a/net/rds/rds.h b/net/rds/rds.h index 254f1345cf7e..0e2797bdc316 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -378,7 +378,6 @@ struct rds_message { } rdma; struct rm_data_op { unsigned int op_active:1; - unsigned int op_notify:1; unsigned int op_nents; unsigned int op_count; unsigned int op_dmasg; @@ -401,11 +400,6 @@ struct rds_notifier { int n_status; }; -/* Available as part of RDS core, so doesn't need to participate - * in get_preferred transport etc - */ -#define RDS_TRANS_LOOP 3 - /** * struct rds_transport - transport specific behavioural hooks * diff --git a/net/rds/recv.c b/net/rds/recv.c index 3843965ee059..2433dec22f71 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -76,11 +76,6 @@ static void rds_recv_rcvbuf_delta(struct rds_sock *rs, struct sock *sk, return; rs->rs_rcv_bytes += delta; - - /* loop transport doesn't send/recv congestion updates */ - if (rs->rs_transport->t_type == RDS_TRANS_LOOP) - return; - now_congested = rs->rs_rcv_bytes > rds_sk_rcvbuf(rs); rdsdebug("rs %p (%pI4:%u) recv bytes %d buf %d " @@ -552,7 +547,5 @@ void rds_inc_info_copy(struct rds_incoming *inc, minfo.flags = 0; - minfo.flags = 0; - rds_info_copy(iter, &minfo, sizeof(minfo)); } diff --git a/net/rds/send.c b/net/rds/send.c index 1a3c6acdd3f8..c9cdb358ea88 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -467,14 +467,12 @@ void rds_rdma_send_complete(struct rds_message *rm, int status) struct rm_rdma_op *ro; struct rds_notifier *notifier; unsigned long flags; - unsigned int notify = 0; spin_lock_irqsave(&rm->m_rs_lock, flags); - notify = rm->rdma.op_notify | rm->data.op_notify; ro = &rm->rdma; if (test_bit(RDS_MSG_ON_SOCK, &rm->m_flags) && - ro->op_active && notify && ro->op_notifier) { + ro->op_active && ro->op_notify && ro->op_notifier) { notifier = ro->op_notifier; rs = rm->m_rs; sock_hold(rds_rs_to_sk(rs)); @@ -959,11 +957,6 @@ static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm, ret = rds_cmsg_rdma_map(rs, rm, cmsg); if (!ret) *allocated_mr = 1; - else if (ret == -ENODEV) - /* Accommodate the get_mr() case which can fail - * if connection isn't established yet. - */ - ret = -EAGAIN; break; case RDS_CMSG_ATOMIC_CSWP: case RDS_CMSG_ATOMIC_FADD: @@ -1077,12 +1070,8 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len) /* Parse any control messages the user may have included. */ ret = rds_cmsg_send(rs, rm, msg, &allocated_mr); - if (ret) { - /* Trigger connection so that its ready for the next retry */ - if (ret == -EAGAIN) - rds_conn_connect_if_down(conn); + if (ret) goto out; - } if (rm->rdma.op_active && !conn->c_trans->xmit_rdma) { printk_ratelimited(KERN_NOTICE "rdma_op %p conn xmit_rdma %p\n", diff --git a/net/rds/tcp.c b/net/rds/tcp.c index 18e50a8fc05f..9d6ddbacd875 100644 --- a/net/rds/tcp.c +++ b/net/rds/tcp.c @@ -421,7 +421,7 @@ static int rds_tcp_init(void) ret = rds_tcp_recv_init(); if (ret) - goto out_pernet; + goto out_slab; ret = rds_trans_register(&rds_tcp_transport); if (ret) @@ -433,9 +433,8 @@ static int rds_tcp_init(void) out_recv: rds_tcp_recv_exit(); -out_pernet: - unregister_pernet_subsys(&rds_tcp_net_ops); out_slab: + unregister_pernet_subsys(&rds_tcp_net_ops); kmem_cache_destroy(rds_tcp_conn_slab); out: return ret; diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index e353e3255206..0936a4a32b47 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c @@ -78,7 +78,7 @@ int rds_tcp_accept_one(struct socket *sock) struct inet_sock *inet; struct rds_tcp_connection *rs_tcp; - ret = sock_create_lite(sock->sk->sk_family, + ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family, sock->sk->sk_type, sock->sk->sk_protocol, &new_sock); if (ret) diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c index e6e249cc651c..93127220cb54 100644 --- a/net/rfkill/rfkill-gpio.c +++ b/net/rfkill/rfkill-gpio.c @@ -140,18 +140,13 @@ static int rfkill_gpio_probe(struct platform_device *pdev) ret = rfkill_register(rfkill->rfkill_dev); if (ret < 0) - goto err_destroy; + return ret; platform_set_drvdata(pdev, rfkill); dev_info(&pdev->dev, "%s device registered.\n", rfkill->name); return 0; - -err_destroy: - rfkill_destroy(rfkill->rfkill_dev); - - return ret; } static int rfkill_gpio_remove(struct platform_device *pdev) diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 91d43ab3a961..da3cc09f683e 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -215,7 +215,7 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, unsigned int *_toklen) { const __be32 *xdr = *_xdr; - unsigned int toklen = *_toklen, n_parts, loop, tmp, paddedlen; + unsigned int toklen = *_toklen, n_parts, loop, tmp; /* there must be at least one name, and at least #names+1 length * words */ @@ -245,16 +245,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, toklen -= 4; if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX) return -EINVAL; - paddedlen = (tmp + 3) & ~3; - if (paddedlen > toklen) + if (tmp > toklen) return -EINVAL; princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL); if (!princ->name_parts[loop]) return -ENOMEM; memcpy(princ->name_parts[loop], xdr, tmp); princ->name_parts[loop][tmp] = 0; - toklen -= paddedlen; - xdr += paddedlen >> 2; + tmp = (tmp + 3) & ~3; + toklen -= tmp; + xdr += tmp >> 2; } if (toklen < 4) @@ -263,16 +263,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, toklen -= 4; if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX) return -EINVAL; - paddedlen = (tmp + 3) & ~3; - if (paddedlen > toklen) + if (tmp > toklen) return -EINVAL; princ->realm = kmalloc(tmp + 1, GFP_KERNEL); if (!princ->realm) return -ENOMEM; memcpy(princ->realm, xdr, tmp); princ->realm[tmp] = 0; - toklen -= paddedlen; - xdr += paddedlen >> 2; + tmp = (tmp + 3) & ~3; + toklen -= tmp; + xdr += tmp >> 2; _debug("%s/...@%s", princ->name_parts[0], princ->realm); @@ -291,7 +291,7 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, unsigned int *_toklen) { const __be32 *xdr = *_xdr; - unsigned int toklen = *_toklen, len, paddedlen; + unsigned int toklen = *_toklen, len; /* there must be at least one tag and one length word */ if (toklen <= 8) @@ -305,17 +305,15 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, toklen -= 8; if (len > max_data_size) return -EINVAL; - paddedlen = (len + 3) & ~3; - if (paddedlen > toklen) - return -EINVAL; td->data_len = len; if (len > 0) { td->data = kmemdup(xdr, len, GFP_KERNEL); if (!td->data) return -ENOMEM; - toklen -= paddedlen; - xdr += paddedlen >> 2; + len = (len + 3) & ~3; + toklen -= len; + xdr += len >> 2; } _debug("tag %x len %x", td->tag, td->data_len); @@ -387,7 +385,7 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, const __be32 **_xdr, unsigned int *_toklen) { const __be32 *xdr = *_xdr; - unsigned int toklen = *_toklen, len, paddedlen; + unsigned int toklen = *_toklen, len; /* there must be at least one length word */ if (toklen <= 4) @@ -399,9 +397,6 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, toklen -= 4; if (len > AFSTOKEN_K5_TIX_MAX) return -EINVAL; - paddedlen = (len + 3) & ~3; - if (paddedlen > toklen) - return -EINVAL; *_tktlen = len; _debug("ticket len %u", len); @@ -410,8 +405,9 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, *_ticket = kmemdup(xdr, len, GFP_KERNEL); if (!*_ticket) return -ENOMEM; - toklen -= paddedlen; - xdr += paddedlen >> 2; + len = (len + 3) & ~3; + toklen -= len; + xdr += len >> 2; } *_xdr = xdr; @@ -554,7 +550,7 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) { const __be32 *xdr = prep->data, *token; const char *cp; - unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix; + unsigned int len, tmp, loop, ntoken, toklen, sec_ix; size_t datalen = prep->datalen; int ret; @@ -580,21 +576,22 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) if (len < 1 || len > AFSTOKEN_CELL_MAX) goto not_xdr; datalen -= 4; - paddedlen = (len + 3) & ~3; - if (paddedlen > datalen) + tmp = (len + 3) & ~3; + if (tmp > datalen) goto not_xdr; cp = (const char *) xdr; for (loop = 0; loop < len; loop++) if (!isprint(cp[loop])) goto not_xdr; - for (; loop < paddedlen; loop++) - if (cp[loop]) - goto not_xdr; + if (len < tmp) + for (; loop < tmp; loop++) + if (cp[loop]) + goto not_xdr; _debug("cellname: [%u/%u] '%*.*s'", - len, paddedlen, len, len, (const char *) xdr); - datalen -= paddedlen; - xdr += paddedlen >> 2; + len, tmp, len, len, (const char *) xdr); + datalen -= tmp; + xdr += tmp >> 2; /* get the token count */ if (datalen < 12) @@ -615,11 +612,10 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) sec_ix = ntohl(*xdr); datalen -= 4; _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix); - paddedlen = (toklen + 3) & ~3; - if (toklen < 20 || toklen > datalen || paddedlen > datalen) + if (toklen < 20 || toklen > datalen) goto not_xdr; - datalen -= paddedlen; - xdr += paddedlen >> 2; + datalen -= (toklen + 3) & ~3; + xdr += (toklen + 3) >> 2; } while (--loop > 0); diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index 6c65fb229e50..d7a9ab5a9d9c 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -209,7 +209,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, struct sk_buff *trailer; unsigned int len; u16 check; - int nsg, err; + int nsg; sp = rxrpc_skb(skb); @@ -240,9 +240,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, len &= ~(call->conn->size_align - 1); sg_init_table(sg, nsg); - err = skb_to_sgvec(skb, sg, 0, len); - if (unlikely(err < 0)) - return err; + skb_to_sgvec(skb, sg, 0, len); crypto_blkcipher_encrypt_iv(&desc, sg, sg, len); _leave(" = 0"); @@ -338,7 +336,7 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, struct sk_buff *trailer; u32 data_size, buf; u16 check; - int nsg, ret; + int nsg; _enter(""); @@ -350,9 +348,7 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, goto nomem; sg_init_table(sg, nsg); - ret = skb_to_sgvec(skb, sg, 0, 8); - if (unlikely(ret < 0)) - return ret; + skb_to_sgvec(skb, sg, 0, 8); /* start the decryption afresh */ memset(&iv, 0, sizeof(iv)); @@ -415,7 +411,7 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, struct sk_buff *trailer; u32 data_size, buf; u16 check; - int nsg, ret; + int nsg; _enter(",{%d}", skb->len); @@ -434,12 +430,7 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, } sg_init_table(sg, nsg); - ret = skb_to_sgvec(skb, sg, 0, skb->len); - if (unlikely(ret < 0)) { - if (sg != _sg) - kfree(sg); - return ret; - } + skb_to_sgvec(skb, sg, 0, skb->len); /* decrypt from the session key */ token = call->conn->key->payload.data[0]; diff --git a/net/sched/act_api.c b/net/sched/act_api.c index f44fea22d69c..06e7c4a37245 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -101,10 +101,8 @@ static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, a->order = n_i; nest = nla_nest_start(skb, a->order); - if (nest == NULL) { - index--; + if (nest == NULL) goto nla_put_failure; - } err = tcf_action_dump_1(skb, a, 0, 0); if (err < 0) { index--; @@ -822,8 +820,10 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, goto out_module_put; err = a.ops->walk(skb, &dcb, RTM_DELACTION, &a); - if (err <= 0) + if (err < 0) goto out_module_put; + if (err == 0) + goto noflush_out; nla_nest_end(skb, nest); @@ -840,6 +840,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, out_module_put: module_put(a.ops->owner); err_out: +noflush_out: kfree_skb(skb); return err; } diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c index bd155e59be1c..0bc6f912f870 100644 --- a/net/sched/act_bpf.c +++ b/net/sched/act_bpf.c @@ -249,14 +249,10 @@ static int tcf_bpf_init_from_efd(struct nlattr **tb, struct tcf_bpf_cfg *cfg) static void tcf_bpf_cfg_cleanup(const struct tcf_bpf_cfg *cfg) { - struct bpf_prog *filter = cfg->filter; - - if (filter) { - if (cfg->is_ebpf) - bpf_prog_put(filter); - else - bpf_prog_destroy(filter); - } + if (cfg->is_ebpf) + bpf_prog_put(cfg->filter); + else + bpf_prog_destroy(cfg->filter); kfree(cfg->bpf_ops); kfree(cfg->bpf_name); diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c index 7ecb14f3db54..bb41699c6c49 100644 --- a/net/sched/act_connmark.c +++ b/net/sched/act_connmark.c @@ -109,9 +109,6 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, if (ret < 0) return ret; - if (!tb[TCA_CONNMARK_PARMS]) - return -EINVAL; - parm = nla_data(tb[TCA_CONNMARK_PARMS]); if (!tcf_hash_check(parm->index, a, bind)) { diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index 024d6cf342c5..b07c535ba8e7 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c @@ -105,7 +105,9 @@ static void *tcf_csum_skb_nextlayer(struct sk_buff *skb, int hl = ihl + jhl; if (!pskb_may_pull(skb, ipl + ntkoff) || (ipl < hl) || - skb_try_make_writable(skb, hl + ntkoff)) + (skb_cloned(skb) && + !skb_clone_writable(skb, hl + ntkoff) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) return NULL; else return (void *)(skb_network_header(skb) + ihl); @@ -175,9 +177,6 @@ static int tcf_csum_ipv4_tcp(struct sk_buff *skb, struct tcphdr *tcph; const struct iphdr *iph; - if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) - return 1; - tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph)); if (tcph == NULL) return 0; @@ -199,9 +198,6 @@ static int tcf_csum_ipv6_tcp(struct sk_buff *skb, struct tcphdr *tcph; const struct ipv6hdr *ip6h; - if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - return 1; - tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph)); if (tcph == NULL) return 0; @@ -225,9 +221,6 @@ static int tcf_csum_ipv4_udp(struct sk_buff *skb, const struct iphdr *iph; u16 ul; - if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_UDP) - return 1; - /* * Support both UDP and UDPLITE checksum algorithms, Don't use * udph->len to get the real length without any protocol check, @@ -281,9 +274,6 @@ static int tcf_csum_ipv6_udp(struct sk_buff *skb, const struct ipv6hdr *ip6h; u16 ul; - if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_UDP) - return 1; - /* * Support both UDP and UDPLITE checksum algorithms, Don't use * udph->len to get the real length without any protocol check, @@ -375,7 +365,9 @@ static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags) } if (update_flags & TCA_CSUM_UPDATE_FLAG_IPV4HDR) { - if (skb_try_make_writable(skb, sizeof(*iph) + ntkoff)) + if (skb_cloned(skb) && + !skb_clone_writable(skb, sizeof(*iph) + ntkoff) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) goto fail; ip_send_check(ip_hdr(skb)); diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 075b0d22f213..d05869646515 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -34,7 +34,6 @@ static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int { struct xt_tgchk_param par; struct xt_target *target; - struct ipt_entry e = {}; int ret = 0; target = xt_request_find_target(AF_INET, t->u.user.name, @@ -43,9 +42,8 @@ static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int return PTR_ERR(target); t->u.kernel.target = target; - memset(&par, 0, sizeof(par)); par.table = table; - par.entryinfo = &e; + par.entryinfo = NULL; par.target = target; par.targinfo = t->data; par.hook_mask = hook; diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 22bbae47dbcb..9eec98690fad 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -36,15 +36,14 @@ static DEFINE_SPINLOCK(mirred_list_lock); static void tcf_mirred_release(struct tc_action *a, int bind) { struct tcf_mirred *m = to_mirred(a); - struct net_device *dev; + struct net_device *dev = rcu_dereference_protected(m->tcfm_dev, 1); /* We could be called either in a RCU callback or with RTNL lock held. */ spin_lock_bh(&mirred_list_lock); list_del(&m->tcfm_list); - dev = rcu_dereference_protected(m->tcfm_dev, 1); + spin_unlock_bh(&mirred_list_lock); if (dev) dev_put(dev); - spin_unlock_bh(&mirred_list_lock); } static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = { diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index 27607b863aba..b7c4ead8b5a8 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c @@ -126,7 +126,9 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, addr = iph->daddr; if (!((old_addr ^ addr) & mask)) { - if (skb_try_make_writable(skb, sizeof(*iph) + noff)) + if (skb_cloned(skb) && + !skb_clone_writable(skb, sizeof(*iph) + noff) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) goto drop; new_addr &= mask; @@ -154,7 +156,9 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, struct tcphdr *tcph; if (!pskb_may_pull(skb, ihl + sizeof(*tcph) + noff) || - skb_try_make_writable(skb, ihl + sizeof(*tcph) + noff)) + (skb_cloned(skb) && + !skb_clone_writable(skb, ihl + sizeof(*tcph) + noff) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) goto drop; tcph = (void *)(skb_network_header(skb) + ihl); @@ -167,7 +171,9 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, struct udphdr *udph; if (!pskb_may_pull(skb, ihl + sizeof(*udph) + noff) || - skb_try_make_writable(skb, ihl + sizeof(*udph) + noff)) + (skb_cloned(skb) && + !skb_clone_writable(skb, ihl + sizeof(*udph) + noff) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) goto drop; udph = (void *)(skb_network_header(skb) + ihl); @@ -207,8 +213,10 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, if ((old_addr ^ addr) & mask) break; - if (skb_try_make_writable(skb, ihl + sizeof(*icmph) + - sizeof(*iph) + noff)) + if (skb_cloned(skb) && + !skb_clone_writable(skb, ihl + sizeof(*icmph) + + sizeof(*iph) + noff) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) goto drop; icmph = (void *)(skb_network_header(skb) + ihl); diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index c3434e902445..e38a7701f154 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -104,17 +104,6 @@ static void tcf_pedit_cleanup(struct tc_action *a, int bind) kfree(keys); } -static bool offset_valid(struct sk_buff *skb, int offset) -{ - if (offset > 0 && offset > skb->len) - return false; - - if (offset < 0 && -offset > skb_headroom(skb)) - return false; - - return true; -} - static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, struct tcf_result *res) { @@ -141,11 +130,6 @@ static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, if (tkey->offmask) { char *d, _d; - if (!offset_valid(skb, off + tkey->at)) { - pr_info("tc filter pedit 'at' offset %d out of bounds\n", - off + tkey->at); - goto bad; - } d = skb_header_pointer(skb, off + tkey->at, 1, &_d); if (!d) @@ -158,10 +142,10 @@ static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, " offset must be on 32 bit boundaries\n"); goto bad; } - - if (!offset_valid(skb, off + offset)) { - pr_info("tc filter pedit offset %d out of bounds\n", - offset); + if (offset > 0 && offset > skb->len) { + pr_info("tc filter pedit" + " offset %d can't exceed pkt length %d\n", + offset, skb->len); goto bad; } diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c index d7edba4536bd..796785e0bf96 100644 --- a/net/sched/act_vlan.c +++ b/net/sched/act_vlan.c @@ -33,12 +33,6 @@ static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a, bstats_update(&v->tcf_bstats, skb); action = v->tcf_action; - /* Ensure 'data' points at mac_header prior calling vlan manipulating - * functions. - */ - if (skb_at_tc_ingress(skb)) - skb_push_rcsum(skb, skb->mac_len); - switch (v->tcfv_action) { case TCA_VLAN_ACT_POP: err = skb_vlan_pop(skb); @@ -60,9 +54,6 @@ static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a, action = TC_ACT_SHOT; v->tcf_qstats.drops++; unlock: - if (skb_at_tc_ingress(skb)) - skb_pull_rcsum(skb, skb->mac_len); - spin_unlock(&v->tcf_lock); return action; } diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 20b2f867c5a1..a75864d93142 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -137,15 +137,13 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) unsigned long cl; unsigned long fh; int err; - int tp_created; + int tp_created = 0; if ((n->nlmsg_type != RTM_GETTFILTER) && !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) return -EPERM; replay: - tp_created = 0; - err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL); if (err < 0) return err; @@ -317,8 +315,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) if (err == 0) { struct tcf_proto *next = rtnl_dereference(tp->next); - tfilter_notify(net, skb, n, tp, - t->tcm_handle, RTM_DELTFILTER); + tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); if (tcf_destroy(tp, false)) RCU_INIT_POINTER(*back, next); } diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 1bf1f4517db6..0b8c3ace671f 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c @@ -62,6 +62,9 @@ static unsigned long basic_get(struct tcf_proto *tp, u32 handle) struct basic_head *head = rtnl_dereference(tp->root); struct basic_filter *f; + if (head == NULL) + return 0UL; + list_for_each_entry(f, &head->flist, link) { if (f->handle == handle) { l = (unsigned long) f; @@ -106,6 +109,7 @@ static bool basic_destroy(struct tcf_proto *tp, bool force) tcf_unbind_filter(tp, &f->res); call_rcu(&f->rcu, basic_delete_filter); } + RCU_INIT_POINTER(tp->root, NULL); kfree_rcu(head, rcu); return true; } diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 3eef0215e53f..5faaa5425f7b 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -199,6 +199,7 @@ static bool cls_bpf_destroy(struct tcf_proto *tp, bool force) call_rcu(&prog->rcu, __cls_bpf_delete_prog); } + RCU_INIT_POINTER(tp->root, NULL); kfree_rcu(head, rcu); return true; } @@ -209,6 +210,9 @@ static unsigned long cls_bpf_get(struct tcf_proto *tp, u32 handle) struct cls_bpf_prog *prog; unsigned long ret = 0UL; + if (head == NULL) + return 0UL; + list_for_each_entry(prog, &head->plist, link) { if (prog->handle == handle) { ret = (unsigned long) prog; diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index c104c2019feb..4c85bd3a750c 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c @@ -130,10 +130,11 @@ static bool cls_cgroup_destroy(struct tcf_proto *tp, bool force) if (!force) return false; - /* Head can still be NULL due to cls_cgroup_init(). */ - if (head) - call_rcu(&head->rcu, cls_cgroup_destroy_rcu); + if (head) { + RCU_INIT_POINTER(tp->root, NULL); + call_rcu(&head->rcu, cls_cgroup_destroy_rcu); + } return true; } diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index d7ba2b4ff0f3..fbfec6a18839 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c @@ -583,6 +583,7 @@ static bool flow_destroy(struct tcf_proto *tp, bool force) list_del_rcu(&f->list); call_rcu(&f->rcu, flow_destroy_filter); } + RCU_INIT_POINTER(tp->root, NULL); kfree_rcu(head, rcu); return true; } diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index e5a58c82728a..95b021243233 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -56,10 +55,7 @@ struct cls_fl_head { bool mask_assigned; struct list_head filters; struct rhashtable_params ht_params; - union { - struct work_struct work; - struct rcu_head rcu; - }; + struct rcu_head rcu; }; struct cls_fl_filter { @@ -169,24 +165,6 @@ static void fl_destroy_filter(struct rcu_head *head) kfree(f); } -static void fl_destroy_sleepable(struct work_struct *work) -{ - struct cls_fl_head *head = container_of(work, struct cls_fl_head, - work); - if (head->mask_assigned) - rhashtable_destroy(&head->ht); - kfree(head); - module_put(THIS_MODULE); -} - -static void fl_destroy_rcu(struct rcu_head *rcu) -{ - struct cls_fl_head *head = container_of(rcu, struct cls_fl_head, rcu); - - INIT_WORK(&head->work, fl_destroy_sleepable); - schedule_work(&head->work); -} - static bool fl_destroy(struct tcf_proto *tp, bool force) { struct cls_fl_head *head = rtnl_dereference(tp->root); @@ -199,9 +177,10 @@ static bool fl_destroy(struct tcf_proto *tp, bool force) list_del_rcu(&f->list); call_rcu(&f->rcu, fl_destroy_filter); } - - __module_get(THIS_MODULE); - call_rcu(&head->rcu, fl_destroy_rcu); + RCU_INIT_POINTER(tp->root, NULL); + if (head->mask_assigned) + rhashtable_destroy(&head->ht); + kfree_rcu(head, rcu); return true; } diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index 9992dfac6938..f9c9fc075fe6 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h @@ -152,8 +152,7 @@ static int rsvp_classify(struct sk_buff *skb, const struct tcf_proto *tp, return -1; nhptr = ip_hdr(skb); #endif - if (unlikely(!head)) - return -1; + restart: #if RSVP_DST_LEN == 4 diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 040d853f48b9..944c8ff45055 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -382,20 +382,22 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, tcf_bind_filter(tp, &cr.res, base); } + if (old_r) + tcf_exts_change(tp, &r->exts, &e); + else + tcf_exts_change(tp, &cr.exts, &e); + if (old_r && old_r != r) tcindex_filter_result_init(old_r); oldp = p; r->res = cr.res; - tcf_exts_change(tp, &r->exts, &e); - rcu_assign_pointer(tp->root, cp); if (r == &new_filter_result) { struct tcindex_filter *nfp; struct tcindex_filter __rcu **fp; - f->result.res = r->res; tcf_exts_change(tp, &f->result.exts, &r->exts); fp = cp->h + (handle % cp->hash); @@ -501,6 +503,7 @@ static bool tcindex_destroy(struct tcf_proto *tp, bool force) walker.fn = tcindex_destroy_element; tcindex_walk(tp, &walker); + RCU_INIT_POINTER(tp->root, NULL); call_rcu(&p->rcu, __tcindex_destroy); return true; } diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 0118ccee49f2..66d1f44a5146 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1004,9 +1004,6 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, return sch; } - /* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */ - if (ops->destroy) - ops->destroy(sch); err_out3: dev_put(dev); kfree((char *) sch - sch->padded); diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c index 562edd50fa94..3fee70d9814f 100644 --- a/net/sched/sch_blackhole.c +++ b/net/sched/sch_blackhole.c @@ -20,7 +20,7 @@ static int blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch) { qdisc_drop(skb, sch); - return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; + return NET_XMIT_SUCCESS; } static struct sk_buff *blackhole_dequeue(struct Qdisc *sch) diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index e8dcf94a23c8..0a08c860eee4 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c @@ -438,9 +438,6 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt) ctl = nla_data(tb[TCA_CHOKE_PARMS]); - if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) - return -EINVAL; - if (ctl->limit > CHOKE_MAX_QUEUE) return -EINVAL; diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index cce4e6ada7fa..d0dff0cd8186 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -199,13 +199,9 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch) pr_debug("%s(skb %p,sch %p,[qdisc %p])\n", __func__, skb, sch, p); if (p->set_tc_index) { - int wlen = skb_network_offset(skb); - switch (tc_skb_protocol(skb)) { case htons(ETH_P_IP): - wlen += sizeof(struct iphdr); - if (!pskb_may_pull(skb, wlen) || - skb_try_make_writable(skb, wlen)) + if (skb_cow_head(skb, sizeof(struct iphdr))) goto drop; skb->tc_index = ipv4_get_dsfield(ip_hdr(skb)) @@ -213,9 +209,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch) break; case htons(ETH_P_IPV6): - wlen += sizeof(struct ipv6hdr); - if (!pskb_may_pull(skb, wlen) || - skb_try_make_writable(skb, wlen)) + if (skb_cow_head(skb, sizeof(struct ipv6hdr))) goto drop; skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb)) diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index 2e4bd2c0a50c..2177eac0a61e 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c @@ -37,18 +37,14 @@ static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch) static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc *sch) { - unsigned int prev_backlog; - if (likely(skb_queue_len(&sch->q) < sch->limit)) return qdisc_enqueue_tail(skb, sch); - prev_backlog = sch->qstats.backlog; /* queue full, remove one skb to fulfill the limit */ __qdisc_queue_drop_head(sch, &sch->q); qdisc_qstats_drop(sch); qdisc_enqueue_tail(skb, sch); - qdisc_tree_reduce_backlog(sch, 0, prev_backlog - sch->qstats.backlog); return NET_XMIT_CN; } diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 117ed90c5f21..3c6a47d66a04 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c @@ -126,28 +126,6 @@ static bool fq_flow_is_detached(const struct fq_flow *f) return f->next == &detached; } -static bool fq_flow_is_throttled(const struct fq_flow *f) -{ - return f->next == &throttled; -} - -static void fq_flow_add_tail(struct fq_flow_head *head, struct fq_flow *flow) -{ - if (head->first) - head->last->next = flow; - else - head->first = flow; - head->last = flow; - flow->next = NULL; -} - -static void fq_flow_unset_throttled(struct fq_sched_data *q, struct fq_flow *f) -{ - rb_erase(&f->rate_node, &q->delayed); - q->throttled_flows--; - fq_flow_add_tail(&q->old_flows, f); -} - static void fq_flow_set_throttled(struct fq_sched_data *q, struct fq_flow *f) { struct rb_node **p = &q->delayed.rb_node, *parent = NULL; @@ -175,6 +153,15 @@ static void fq_flow_set_throttled(struct fq_sched_data *q, struct fq_flow *f) static struct kmem_cache *fq_flow_cachep __read_mostly; +static void fq_flow_add_tail(struct fq_flow_head *head, struct fq_flow *flow) +{ + if (head->first) + head->last->next = flow; + else + head->first = flow; + head->last = flow; + flow->next = NULL; +} /* limit number of collected flows per round */ #define FQ_GC_MAX 8 @@ -278,8 +265,6 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q) f->socket_hash != sk->sk_hash)) { f->credit = q->initial_quantum; f->socket_hash = sk->sk_hash; - if (fq_flow_is_throttled(f)) - fq_flow_unset_throttled(q, f); f->time_next_packet = 0ULL; } return f; @@ -434,7 +419,9 @@ static void fq_check_throttled(struct fq_sched_data *q, u64 now) q->time_next_delayed_flow = f->time_next_packet; break; } - fq_flow_unset_throttled(q, f); + rb_erase(p, &q->delayed); + q->throttled_flows--; + fq_flow_add_tail(&q->old_flows, f); } } diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index f9e8deeeac96..80105109f756 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -389,9 +389,6 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp, struct gred_sched *table = qdisc_priv(sch); struct gred_sched_data *q = table->tab[dp]; - if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) - return -EINVAL; - if (!q) { table->tab[dp] = q = *prealloc; *prealloc = NULL; diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c index 45d4b2f22f62..13d6f83ec491 100644 --- a/net/sched/sch_hhf.c +++ b/net/sched/sch_hhf.c @@ -636,9 +636,7 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt) q->hhf_arrays[i] = hhf_zalloc(HHF_ARRAYS_LEN * sizeof(u32)); if (!q->hhf_arrays[i]) { - /* Note: hhf_destroy() will be called - * by our caller. - */ + hhf_destroy(sch); return -ENOMEM; } } @@ -649,9 +647,7 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt) q->hhf_valid_bits[i] = hhf_zalloc(HHF_ARRAYS_LEN / BITS_PER_BYTE); if (!q->hhf_valid_bits[i]) { - /* Note: hhf_destroy() will be called - * by our caller. - */ + hhf_destroy(sch); return -ENOMEM; } } diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c index d9c84328e7eb..3e82f047caaf 100644 --- a/net/sched/sch_mq.c +++ b/net/sched/sch_mq.c @@ -52,7 +52,7 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt) /* pre-allocate qdiscs, attachment can't fail */ priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]), GFP_KERNEL); - if (!priv->qdiscs) + if (priv->qdiscs == NULL) return -ENOMEM; for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { @@ -60,14 +60,18 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt) qdisc = qdisc_create_dflt(dev_queue, default_qdisc_ops, TC_H_MAKE(TC_H_MAJ(sch->handle), TC_H_MIN(ntx + 1))); - if (!qdisc) - return -ENOMEM; + if (qdisc == NULL) + goto err; priv->qdiscs[ntx] = qdisc; qdisc->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT; } sch->flags |= TCQ_F_MQROOT; return 0; + +err: + mq_destroy(sch); + return -ENOMEM; } static void mq_attach(struct Qdisc *sch) diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c index 66bccc5ff4ea..ad70ecf57ce7 100644 --- a/net/sched/sch_mqprio.c +++ b/net/sched/sch_mqprio.c @@ -117,17 +117,20 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) /* pre-allocate qdisc, attachment can't fail */ priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]), GFP_KERNEL); - if (!priv->qdiscs) - return -ENOMEM; + if (priv->qdiscs == NULL) { + err = -ENOMEM; + goto err; + } for (i = 0; i < dev->num_tx_queues; i++) { dev_queue = netdev_get_tx_queue(dev, i); qdisc = qdisc_create_dflt(dev_queue, default_qdisc_ops, TC_H_MAKE(TC_H_MAJ(sch->handle), TC_H_MIN(i + 1))); - if (!qdisc) - return -ENOMEM; - + if (qdisc == NULL) { + err = -ENOMEM; + goto err; + } priv->qdiscs[i] = qdisc; qdisc->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT; } @@ -140,7 +143,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) priv->hw_owned = 1; err = dev->netdev_ops->ndo_setup_tc(dev, qopt->num_tc); if (err) - return err; + goto err; } else { netdev_set_num_tc(dev, qopt->num_tc); for (i = 0; i < qopt->num_tc; i++) @@ -154,6 +157,10 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) sch->flags |= TCQ_F_MQROOT; return 0; + +err: + mqprio_destroy(sch); + return err; } static void mqprio_attach(struct Qdisc *sch) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index b7c29d5b6f04..4befe97a9034 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -650,14 +650,14 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) #endif if (q->qdisc) { - unsigned int pkt_len = qdisc_pkt_len(skb); int err = qdisc_enqueue(skb, q->qdisc); - if (err != NET_XMIT_SUCCESS && - net_xmit_drop_count(err)) { - qdisc_qstats_drop(sch); - qdisc_tree_reduce_backlog(sch, 1, - pkt_len); + if (unlikely(err != NET_XMIT_SUCCESS)) { + if (net_xmit_drop_count(err)) { + qdisc_qstats_drop(sch); + qdisc_tree_reduce_backlog(sch, 1, + qdisc_pkt_len(skb)); + } } goto tfifo_dequeue; } diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 0505b8408c8b..8c0508c0e287 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -199,8 +199,6 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) max_P = tb[TCA_RED_MAX_P] ? nla_get_u32(tb[TCA_RED_MAX_P]) : 0; ctl = nla_data(tb[TCA_RED_PARMS]); - if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) - return -EINVAL; if (ctl->limit > 0) { child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit); diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 8b8c084b32cd..498f0a2cb47f 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -434,7 +434,6 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) qdisc_drop(head, sch); slot_queue_add(slot, skb); - qdisc_tree_reduce_backlog(sch, 0, delta); return NET_XMIT_CN; } @@ -466,10 +465,8 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) /* Return Congestion Notification only if we dropped a packet * from this flow. */ - if (qlen != slot->qlen) { - qdisc_tree_reduce_backlog(sch, 0, dropped - qdisc_pkt_len(skb)); + if (qlen != slot->qlen) return NET_XMIT_CN; - } /* As we dropped a packet, better let upper stack know this */ qdisc_tree_reduce_backlog(sch, 1, dropped); @@ -633,9 +630,6 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt) if (ctl->divisor && (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536)) return -EINVAL; - if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max, - ctl_v1->Wlog)) - return -EINVAL; if (ctl_v1 && ctl_v1->qth_min) { p = kmalloc(sizeof(*p), GFP_KERNEL); if (!p) @@ -748,10 +742,9 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt) q->ht = sfq_alloc(sizeof(q->ht[0]) * q->divisor); q->slots = sfq_alloc(sizeof(q->slots[0]) * q->maxflows); if (!q->ht || !q->slots) { - /* Note: sfq_destroy() will be called by our caller */ + sfq_destroy(sch); return -ENOMEM; } - for (i = 0; i < q->divisor; i++) q->ht[i] = SFQ_EMPTY_SLOT; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index a40b8b0ef0d5..559afd0ee7de 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1000,10 +1000,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) struct sctp_endpoint *ep; struct sctp_chunk *chunk; struct sctp_inq *inqueue; + int state; sctp_subtype_t subtype; - int first_time = 1; /* is this the first time through the loop */ int error = 0; - int state; /* The association should be held so we should be safe. */ ep = asoc->ep; @@ -1014,30 +1013,6 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) state = asoc->state; subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type); - /* If the first chunk in the packet is AUTH, do special - * processing specified in Section 6.3 of SCTP-AUTH spec - */ - if (first_time && subtype.chunk == SCTP_CID_AUTH) { - struct sctp_chunkhdr *next_hdr; - - next_hdr = sctp_inq_peek(inqueue); - if (!next_hdr) - goto normal; - - /* If the next chunk is COOKIE-ECHO, skip the AUTH - * chunk while saving a pointer to it so we can do - * Authentication later (during cookie-echo - * processing). - */ - if (next_hdr->type == SCTP_CID_COOKIE_ECHO) { - chunk->auth_chunk = skb_clone(chunk->skb, - GFP_ATOMIC); - chunk->auth = 1; - continue; - } - } - -normal: /* SCTP-AUTH, Section 6.3: * The receiver has a list of chunk types which it expects * to be received only after an AUTH-chunk. This list has @@ -1076,9 +1051,6 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) /* If there is an error on chunk, discard this packet. */ if (error && chunk) chunk->pdiscard = 1; - - if (first_time) - first_time = 0; } sctp_association_put(asoc); } diff --git a/net/sctp/debug.c b/net/sctp/debug.c index e371a0d90068..95d7b15dad21 100644 --- a/net/sctp/debug.c +++ b/net/sctp/debug.c @@ -166,7 +166,7 @@ static const char *const sctp_timer_tbl[] = { /* Lookup timer debug name. */ const char *sctp_tname(const sctp_subtype_t id) { - if (id.timeout < ARRAY_SIZE(sctp_timer_tbl)) + if (id.timeout <= SCTP_EVENT_TIMEOUT_MAX) return sctp_timer_tbl[id.timeout]; return "unknown_timer"; } diff --git a/net/sctp/input.c b/net/sctp/input.c index 71c2ef84c5b0..b6493b3f11a9 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -420,7 +420,7 @@ void sctp_icmp_redirect(struct sock *sk, struct sctp_transport *t, { struct dst_entry *dst; - if (sock_owned_by_user(sk) || !t) + if (!t) return; dst = sctp_transport_dst_check(t); if (dst) @@ -472,14 +472,15 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb, struct sctp_association **app, struct sctp_transport **tpp) { - struct sctp_init_chunk *chunkhdr, _chunkhdr; union sctp_addr saddr; union sctp_addr daddr; struct sctp_af *af; struct sock *sk = NULL; struct sctp_association *asoc; struct sctp_transport *transport = NULL; + struct sctp_init_chunk *chunkhdr; __u32 vtag = ntohl(sctphdr->vtag); + int len = skb->len - ((void *)sctphdr - (void *)skb->data); *app = NULL; *tpp = NULL; @@ -514,16 +515,13 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb, * discard the packet. */ if (vtag == 0) { - /* chunk header + first 4 octects of init header */ - chunkhdr = skb_header_pointer(skb, skb_transport_offset(skb) + - sizeof(struct sctphdr), - sizeof(struct sctp_chunkhdr) + - sizeof(__be32), &_chunkhdr); - if (!chunkhdr || + chunkhdr = (void *)sctphdr + sizeof(struct sctphdr); + if (len < sizeof(struct sctphdr) + sizeof(sctp_chunkhdr_t) + + sizeof(__be32) || chunkhdr->chunk_hdr.type != SCTP_CID_INIT || - ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) + ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) { goto out; - + } } else if (vtag != asoc->c.peer_vtag) { goto out; } diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index 8d9b7ad25b65..7e8a16c77039 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -178,7 +178,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); chunk->subh.v = NULL; /* Subheader is no longer valid. */ - if (chunk->chunk_end + sizeof(sctp_chunkhdr_t) <= + if (chunk->chunk_end + sizeof(sctp_chunkhdr_t) < skb_tail_pointer(chunk->skb)) { /* This is not a singleton */ chunk->singleton = 0; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 5ca8309ea7b1..35672243d4a0 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -239,10 +239,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, struct sctp_bind_addr *bp; struct ipv6_pinfo *np = inet6_sk(sk); struct sctp_sockaddr_entry *laddr; + union sctp_addr *baddr = NULL; union sctp_addr *daddr = &t->ipaddr; union sctp_addr dst_saddr; struct in6_addr *final_p, final; __u8 matchlen = 0; + __u8 bmatchlen; sctp_scope_t scope; memset(fl6, 0, sizeof(struct flowi6)); @@ -309,41 +311,23 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, */ rcu_read_lock(); list_for_each_entry_rcu(laddr, &bp->address_list, list) { - struct dst_entry *bdst; - __u8 bmatchlen; - - if (!laddr->valid || - laddr->state != SCTP_ADDR_SRC || - laddr->a.sa.sa_family != AF_INET6 || - scope > sctp_scope(&laddr->a)) - continue; - - fl6->saddr = laddr->a.v6.sin6_addr; - fl6->fl6_sport = laddr->a.v6.sin6_port; - final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); - bdst = ip6_dst_lookup_flow(sk, fl6, final_p); - - if (IS_ERR(bdst)) - continue; - - if (ipv6_chk_addr(dev_net(bdst->dev), - &laddr->a.v6.sin6_addr, bdst->dev, 1)) { - if (!IS_ERR_OR_NULL(dst)) - dst_release(dst); - dst = bdst; - break; - } - - bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); - if (matchlen > bmatchlen) { - dst_release(bdst); + if (!laddr->valid) continue; + if ((laddr->state == SCTP_ADDR_SRC) && + (laddr->a.sa.sa_family == AF_INET6) && + (scope <= sctp_scope(&laddr->a))) { + bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); + if (!baddr || (matchlen < bmatchlen)) { + baddr = &laddr->a; + matchlen = bmatchlen; + } } - - if (!IS_ERR_OR_NULL(dst)) - dst_release(dst); - dst = bdst; - matchlen = bmatchlen; + } + if (baddr) { + fl6->saddr = baddr->v6.sin6_addr; + fl6->fl6_sport = baddr->v6.sin6_port; + final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); + dst = ip6_dst_lookup_flow(sk, fl6, final_p); } rcu_read_unlock(); @@ -514,54 +498,49 @@ static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr, { addr->sa.sa_family = AF_INET6; addr->v6.sin6_port = port; - addr->v6.sin6_flowinfo = 0; addr->v6.sin6_addr = *saddr; - addr->v6.sin6_scope_id = 0; } -static int __sctp_v6_cmp_addr(const union sctp_addr *addr1, - const union sctp_addr *addr2) +/* Compare addresses exactly. + * v4-mapped-v6 is also in consideration. + */ +static int sctp_v6_cmp_addr(const union sctp_addr *addr1, + const union sctp_addr *addr2) { if (addr1->sa.sa_family != addr2->sa.sa_family) { if (addr1->sa.sa_family == AF_INET && addr2->sa.sa_family == AF_INET6 && - ipv6_addr_v4mapped(&addr2->v6.sin6_addr) && - addr2->v6.sin6_addr.s6_addr32[3] == - addr1->v4.sin_addr.s_addr) - return 1; - + ipv6_addr_v4mapped(&addr2->v6.sin6_addr)) { + if (addr2->v6.sin6_port == addr1->v4.sin_port && + addr2->v6.sin6_addr.s6_addr32[3] == + addr1->v4.sin_addr.s_addr) + return 1; + } if (addr2->sa.sa_family == AF_INET && addr1->sa.sa_family == AF_INET6 && - ipv6_addr_v4mapped(&addr1->v6.sin6_addr) && - addr1->v6.sin6_addr.s6_addr32[3] == - addr2->v4.sin_addr.s_addr) - return 1; - + ipv6_addr_v4mapped(&addr1->v6.sin6_addr)) { + if (addr1->v6.sin6_port == addr2->v4.sin_port && + addr1->v6.sin6_addr.s6_addr32[3] == + addr2->v4.sin_addr.s_addr) + return 1; + } return 0; } - + if (addr1->v6.sin6_port != addr2->v6.sin6_port) + return 0; if (!ipv6_addr_equal(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr)) return 0; - /* If this is a linklocal address, compare the scope_id. */ - if ((ipv6_addr_type(&addr1->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) && - addr1->v6.sin6_scope_id && addr2->v6.sin6_scope_id && - addr1->v6.sin6_scope_id != addr2->v6.sin6_scope_id) - return 0; + if (ipv6_addr_type(&addr1->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) { + if (addr1->v6.sin6_scope_id && addr2->v6.sin6_scope_id && + (addr1->v6.sin6_scope_id != addr2->v6.sin6_scope_id)) { + return 0; + } + } return 1; } -/* Compare addresses exactly. - * v4-mapped-v6 is also in consideration. - */ -static int sctp_v6_cmp_addr(const union sctp_addr *addr1, - const union sctp_addr *addr2) -{ - return __sctp_v6_cmp_addr(addr1, addr2) && - addr1->v6.sin6_port == addr2->v6.sin6_port; -} - /* Initialize addr struct to INADDR_ANY. */ static void sctp_v6_inaddr_any(union sctp_addr *addr, __be16 port) { @@ -726,10 +705,8 @@ static int sctp_v6_addr_to_user(struct sctp_sock *sp, union sctp_addr *addr) sctp_v6_map_v4(addr); } - if (addr->sa.sa_family == AF_INET) { - memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); + if (addr->sa.sa_family == AF_INET) return sizeof(struct sockaddr_in); - } return sizeof(struct sockaddr_in6); } @@ -815,8 +792,6 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, if (ipv6_addr_type(&addr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) { struct sctp_ulpevent *ev = sctp_skb2event(skb); addr->v6.sin6_scope_id = ev->iif; - } else { - addr->v6.sin6_scope_id = 0; } } @@ -846,8 +821,8 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, const union sctp_addr *addr2, struct sctp_sock *opt) { - struct sock *sk = sctp_opt2sk(opt); struct sctp_af *af1, *af2; + struct sock *sk = sctp_opt2sk(opt); af1 = sctp_get_af_specific(addr1->sa.sa_family); af2 = sctp_get_af_specific(addr2->sa.sa_family); @@ -863,10 +838,10 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2)) return 1; - if (addr1->sa.sa_family == AF_INET && addr2->sa.sa_family == AF_INET) - return addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr; + if (addr1->sa.sa_family != addr2->sa.sa_family) + return 0; - return __sctp_v6_cmp_addr(addr1, addr2); + return af1->cmp_addr(addr1, addr2); } /* Verify that the provided sockaddr looks bindable. Common verification, diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index dc030efa4447..8b4ff315695e 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -508,20 +508,22 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, if (IS_ERR(rt)) continue; + if (!dst) + dst = &rt->dst; + /* Ensure the src address belongs to the output * interface. */ odev = __ip_dev_find(sock_net(sk), laddr->a.v4.sin_addr.s_addr, false); if (!odev || odev->ifindex != fl4->flowi4_oif) { - if (!dst) - dst = &rt->dst; - else + if (&rt->dst != dst) dst_release(&rt->dst); continue; } - dst_release(dst); + if (dst != &rt->dst) + dst_release(dst); dst = &rt->dst; break; } diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 509e9426a056..5d6a03fad378 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1367,14 +1367,10 @@ static struct sctp_chunk *_sctp_make_chunk(const struct sctp_association *asoc, sctp_chunkhdr_t *chunk_hdr; struct sk_buff *skb; struct sock *sk; - int chunklen; - - chunklen = WORD_ROUND(sizeof(*chunk_hdr) + paylen); - if (chunklen > SCTP_MAX_CHUNK_LEN) - goto nodata; /* No need to allocate LL here, as this is only a chunk. */ - skb = alloc_skb(chunklen, GFP_ATOMIC); + skb = alloc_skb(WORD_ROUND(sizeof(sctp_chunkhdr_t) + paylen), + GFP_ATOMIC); if (!skb) goto nodata; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index a717302147f4..a88336a00c89 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -144,8 +144,10 @@ static sctp_disposition_t sctp_sf_violation_chunk( void *arg, sctp_cmd_seq_t *commands); -static sctp_ierror_t sctp_sf_authenticate( +static sctp_ierror_t sctp_sf_authenticate(struct net *net, + const struct sctp_endpoint *ep, const struct sctp_association *asoc, + const sctp_subtype_t type, struct sctp_chunk *chunk); static sctp_disposition_t __sctp_sf_do_9_1_abort(struct net *net, @@ -613,38 +615,6 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net, return SCTP_DISPOSITION_CONSUME; } -static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk, - const struct sctp_association *asoc) -{ - struct sctp_chunk auth; - - if (!chunk->auth_chunk) - return true; - - /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo - * is supposed to be authenticated and we have to do delayed - * authentication. We've just recreated the association using - * the information in the cookie and now it's much easier to - * do the authentication. - */ - - /* Make sure that we and the peer are AUTH capable */ - if (!net->sctp.auth_enable || !asoc->peer.auth_capable) - return false; - - /* set-up our fake chunk so that we can process it */ - auth.skb = chunk->auth_chunk; - auth.asoc = chunk->asoc; - auth.sctp_hdr = chunk->sctp_hdr; - auth.chunk_hdr = (struct sctp_chunkhdr *) - skb_push(chunk->auth_chunk, - sizeof(struct sctp_chunkhdr)); - skb_pull(chunk->auth_chunk, sizeof(struct sctp_chunkhdr)); - auth.transport = chunk->transport; - - return sctp_sf_authenticate(asoc, &auth) == SCTP_IERROR_NO_ERROR; -} - /* * Respond to a normal COOKIE ECHO chunk. * We are the side that is being asked for an association. @@ -781,9 +751,36 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, if (error) goto nomem_init; - if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) { - sctp_association_free(new_asoc); - return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo + * is supposed to be authenticated and we have to do delayed + * authentication. We've just recreated the association using + * the information in the cookie and now it's much easier to + * do the authentication. + */ + if (chunk->auth_chunk) { + struct sctp_chunk auth; + sctp_ierror_t ret; + + /* Make sure that we and the peer are AUTH capable */ + if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) { + sctp_association_free(new_asoc); + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + } + + /* set-up our fake chunk so that we can process it */ + auth.skb = chunk->auth_chunk; + auth.asoc = chunk->asoc; + auth.sctp_hdr = chunk->sctp_hdr; + auth.chunk_hdr = (sctp_chunkhdr_t *)skb_push(chunk->auth_chunk, + sizeof(sctp_chunkhdr_t)); + skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t)); + auth.transport = chunk->transport; + + ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth); + if (ret != SCTP_IERROR_NO_ERROR) { + sctp_association_free(new_asoc); + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + } } repl = sctp_make_cookie_ack(new_asoc, chunk); @@ -1720,15 +1717,13 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net, GFP_ATOMIC)) goto nomem; - if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) - return SCTP_DISPOSITION_DISCARD; - /* Make sure no new addresses are being added during the * restart. Though this is a pretty complicated attack * since you'd have to get inside the cookie. */ - if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) + if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) { return SCTP_DISPOSITION_CONSUME; + } /* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes * the peer has restarted (Action A), it MUST NOT setup a new @@ -1833,9 +1828,6 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(struct net *net, GFP_ATOMIC)) goto nomem; - if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) - return SCTP_DISPOSITION_DISCARD; - /* Update the content of current association. */ sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, @@ -1928,9 +1920,6 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(struct net *net, * a COOKIE ACK. */ - if (!sctp_auth_chunk_verify(net, chunk, asoc)) - return SCTP_DISPOSITION_DISCARD; - /* Don't accidentally move back into established state. */ if (asoc->state < SCTP_STATE_ESTABLISHED) { sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, @@ -1970,7 +1959,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(struct net *net, } } - repl = sctp_make_cookie_ack(asoc, chunk); + repl = sctp_make_cookie_ack(new_asoc, chunk); if (!repl) goto nomem; @@ -3443,12 +3432,6 @@ sctp_disposition_t sctp_sf_ootb(struct net *net, return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, commands); - /* Report violation if chunk len overflows */ - ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); - if (ch_end > skb_tail_pointer(skb)) - return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, - commands); - /* Now that we know we at least have a chunk header, * do things that are type appropriate. */ @@ -4002,8 +3985,10 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast( * * The return value is the disposition of the chunk. */ -static sctp_ierror_t sctp_sf_authenticate( +static sctp_ierror_t sctp_sf_authenticate(struct net *net, + const struct sctp_endpoint *ep, const struct sctp_association *asoc, + const sctp_subtype_t type, struct sctp_chunk *chunk) { struct sctp_authhdr *auth_hdr; @@ -4102,7 +4087,7 @@ sctp_disposition_t sctp_sf_eat_auth(struct net *net, commands); auth_hdr = (struct sctp_authhdr *)chunk->skb->data; - error = sctp_sf_authenticate(asoc, chunk); + error = sctp_sf_authenticate(net, ep, asoc, type, chunk); switch (error) { case SCTP_IERROR_AUTH_BAD_HMAC: /* Generate the ERROR chunk and discard the rest diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 13c7f42b7040..b3e3ab41db0a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -82,7 +82,7 @@ /* Forward declarations for internal helper functions. */ static int sctp_writeable(struct sock *sk); static void sctp_wfree(struct sk_buff *skb); -static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, +static int sctp_wait_for_sndbuf(struct sctp_association *, long *timeo_p, size_t msg_len); static int sctp_wait_for_packet(struct sock *sk, int *err, long *timeo_p); static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p); @@ -168,36 +168,6 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk) sk_mem_charge(sk, chunk->skb->truesize); } -static void sctp_clear_owner_w(struct sctp_chunk *chunk) -{ - skb_orphan(chunk->skb); -} - -static void sctp_for_each_tx_datachunk(struct sctp_association *asoc, - void (*cb)(struct sctp_chunk *)) - -{ - struct sctp_outq *q = &asoc->outqueue; - struct sctp_transport *t; - struct sctp_chunk *chunk; - - list_for_each_entry(t, &asoc->peer.transport_addr_list, transports) - list_for_each_entry(chunk, &t->transmitted, transmitted_list) - cb(chunk); - - list_for_each_entry(chunk, &q->retransmit, list) - cb(chunk); - - list_for_each_entry(chunk, &q->sacked, list) - cb(chunk); - - list_for_each_entry(chunk, &q->abandoned, list) - cb(chunk); - - list_for_each_entry(chunk, &q->out_chunk_list, list) - cb(chunk); -} - /* Verify that this is a valid address. */ static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr, int len) @@ -265,12 +235,8 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, sctp_assoc_t id) { struct sctp_association *addr_asoc = NULL, *id_asoc = NULL; - struct sctp_af *af = sctp_get_af_specific(addr->ss_family); - union sctp_addr *laddr = (union sctp_addr *)addr; struct sctp_transport *transport; - - if (!af || sctp_verify_addr(sk, laddr, af->sockaddr_len)) - return NULL; + union sctp_addr *laddr = (union sctp_addr *)addr; addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep, laddr, @@ -332,15 +298,14 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt, if (len < sizeof (struct sockaddr)) return NULL; - if (!opt->pf->af_supported(addr->sa.sa_family, opt)) - return NULL; - - if (addr->sa.sa_family == AF_INET6) { - if (len < SIN6_LEN_RFC2133) + /* V4 mapped address are really of AF_INET family */ + if (addr->sa.sa_family == AF_INET6 && + ipv6_addr_v4mapped(&addr->v6.sin6_addr)) { + if (!opt->pf->af_supported(AF_INET, opt)) return NULL; - /* V4 mapped address are really of AF_INET family */ - if (ipv6_addr_v4mapped(&addr->v6.sin6_addr) && - !opt->pf->af_supported(AF_INET, opt)) + } else { + /* Does this PF support this AF? */ + if (!opt->pf->af_supported(addr->sa.sa_family, opt)) return NULL; } @@ -1247,12 +1212,9 @@ static int __sctp_connect(struct sock *sk, timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); - if (assoc_id) - *assoc_id = asoc->assoc_id; err = sctp_wait_for_connect(asoc, &timeo); - /* Note: the asoc may be freed after the return of - * sctp_wait_for_connect. - */ + if ((err == 0 || err == -EINPROGRESS) && assoc_id) + *assoc_id = asoc->assoc_id; /* Don't free association on exit. */ asoc = NULL; @@ -1521,7 +1483,7 @@ static void sctp_close(struct sock *sk, long timeout) pr_debug("%s: sk:%p, timeout:%ld\n", __func__, sk, timeout); - lock_sock_nested(sk, SINGLE_DEPTH_NESTING); + lock_sock(sk); sk->sk_shutdown = SHUTDOWN_MASK; sk->sk_state = SCTP_SS_CLOSING; @@ -1572,7 +1534,7 @@ static void sctp_close(struct sock *sk, long timeout) * held and that should be grabbed before socket lock. */ spin_lock_bh(&net->sctp.addr_wq_lock); - bh_lock_sock_nested(sk); + bh_lock_sock(sk); /* Hold the sock, since sk_common_release() will put sock_put() * and we have just a little more cleanup. @@ -1954,16 +1916,9 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); if (!sctp_wspace(asoc)) { - /* sk can be changed by peel off when waiting for buf. */ err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len); - if (err) { - if (err == -ESRCH) { - /* asoc is already dead. */ - new_asoc = NULL; - err = -EPIPE; - } + if (err) goto out_free; - } } /* If an address is passed with the sendto/sendmsg call, it is used @@ -4154,7 +4109,7 @@ static int sctp_init_sock(struct sock *sk) SCTP_DBG_OBJCNT_INC(sock); local_bh_disable(); - sk_sockets_allocated_inc(sk); + percpu_counter_inc(&sctp_sockets_allocated); sock_prot_inuse_add(net, sk->sk_prot, 1); /* Nothing can fail after this block, otherwise @@ -4198,7 +4153,7 @@ static void sctp_destroy_sock(struct sock *sk) } sctp_endpoint_free(sp->ep); local_bh_disable(); - sk_sockets_allocated_dec(sk); + percpu_counter_dec(&sctp_sockets_allocated); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); local_bh_enable(); } @@ -4416,7 +4371,7 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len, static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, int __user *optlen) { - if (len == 0) + if (len <= 0) return -EINVAL; if (len > sizeof(struct sctp_event_subscribe)) len = sizeof(struct sctp_event_subscribe); @@ -4448,7 +4403,7 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optv len = sizeof(int); if (put_user(len, optlen)) return -EFAULT; - if (copy_to_user(optval, &sctp_sk(sk)->autoclose, len)) + if (copy_to_user(optval, &sctp_sk(sk)->autoclose, sizeof(int))) return -EFAULT; return 0; } @@ -5025,9 +4980,6 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, err = -EFAULT; goto out; } - /* XXX: We should have accounted for sizeof(struct sctp_getaddrs) too, - * but we can't change it anymore. - */ if (put_user(bytes_copied, optlen)) err = -EFAULT; out: @@ -5464,7 +5416,7 @@ static int sctp_getsockopt_maxseg(struct sock *sk, int len, params.assoc_id = 0; } else if (len >= sizeof(struct sctp_assoc_value)) { len = sizeof(struct sctp_assoc_value); - if (copy_from_user(¶ms, optval, len)) + if (copy_from_user(¶ms, optval, sizeof(params))) return -EFAULT; } else return -EINVAL; @@ -5633,9 +5585,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, if (len < sizeof(struct sctp_authkeyid)) return -EINVAL; - - len = sizeof(struct sctp_authkeyid); - if (copy_from_user(&val, optval, len)) + if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid))) return -EFAULT; asoc = sctp_id2assoc(sk, val.scact_assoc_id); @@ -5647,6 +5597,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, else val.scact_keynumber = ep->active_key_id; + len = sizeof(struct sctp_authkeyid); if (put_user(len, optlen)) return -EFAULT; if (copy_to_user(optval, &val, len)) @@ -5672,7 +5623,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, if (len < sizeof(struct sctp_authchunks)) return -EINVAL; - if (copy_from_user(&val, optval, sizeof(val))) + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) return -EFAULT; to = p->gauth_chunks; @@ -5717,7 +5668,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, if (len < sizeof(struct sctp_authchunks)) return -EINVAL; - if (copy_from_user(&val, optval, sizeof(val))) + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) return -EFAULT; to = p->gauth_chunks; @@ -6025,9 +5976,6 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, if (get_user(len, optlen)) return -EFAULT; - if (len < 0) - return -EINVAL; - lock_sock(sk); switch (optname) { @@ -6438,9 +6386,6 @@ int sctp_inet_listen(struct socket *sock, int backlog) if (sock->state != SS_UNCONNECTED) goto out; - if (!sctp_sstate(sk, LISTENING) && !sctp_sstate(sk, CLOSED)) - goto out; - /* If backlog is zero, disable listening. */ if (!backlog) { if (sctp_sstate(sk, CLOSED)) @@ -6984,9 +6929,9 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, size_t msg_len) { struct sock *sk = asoc->base.sk; + int err = 0; long current_timeo = *timeo_p; DEFINE_WAIT(wait); - int err = 0; pr_debug("%s: asoc:%p, timeo:%ld, msg_len:%zu\n", __func__, asoc, *timeo_p, msg_len); @@ -6998,11 +6943,10 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, for (;;) { prepare_to_wait_exclusive(&asoc->wait, &wait, TASK_INTERRUPTIBLE); - if (asoc->base.dead) - goto do_dead; if (!*timeo_p) goto do_nonblock; - if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING) + if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING || + asoc->base.dead) goto do_error; if (signal_pending(current)) goto do_interrupted; @@ -7014,9 +6958,9 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, */ release_sock(sk); current_timeo = schedule_timeout(current_timeo); - lock_sock(sk); if (sk != asoc->base.sk) goto do_error; + lock_sock(sk); *timeo_p = current_timeo; } @@ -7029,10 +6973,6 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, return err; -do_dead: - err = -ESRCH; - goto out; - do_error: err = -EPIPE; goto out; @@ -7409,9 +7349,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, * paths won't try to lock it and then oldsk. */ lock_sock_nested(newsk, SINGLE_DEPTH_NESTING); - sctp_for_each_tx_datachunk(assoc, sctp_clear_owner_w); sctp_assoc_migrate(assoc, newsk); - sctp_for_each_tx_datachunk(assoc, sctp_set_owner_w); /* If the association on the newsk is already closed before accept() * is called, set RCV_SHUTDOWN flag. diff --git a/net/socket.c b/net/socket.c index fe1c5749bd0b..bb45975fbeff 100644 --- a/net/socket.c +++ b/net/socket.c @@ -89,7 +89,6 @@ #include #include #include -#include #include #include @@ -1728,7 +1727,6 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, /* We assume all kernel code knows the size of sockaddr_storage */ msg.msg_namelen = 0; msg.msg_iocb = NULL; - msg.msg_flags = 0; if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT; err = sock_recvmsg(sock, &msg, iov_iter_count(&msg.msg_iter), flags); @@ -2073,8 +2071,6 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, if (err) break; ++datagrams; - if (msg_data_left(&msg_sys)) - break; } fput_light(sock->file, fput_needed); @@ -2217,10 +2213,8 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, return err; err = sock_error(sock->sk); - if (err) { - datagrams = err; + if (err) goto out_put; - } entry = mmsg; compat_entry = (struct compat_mmsghdr __user *)mmsg; @@ -2355,7 +2349,6 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) if (call < 1 || call > SYS_SENDMMSG) return -EINVAL; - call = array_index_nospec(call, SYS_SENDMMSG + 1); len = nargs[call]; if (len > sizeof(a)) @@ -2566,15 +2559,6 @@ static int __init sock_init(void) core_initcall(sock_init); /* early initcall */ -static int __init jit_init(void) -{ -#ifdef CONFIG_BPF_JIT_ALWAYS_ON - bpf_jit_enable = 1; -#endif - return 0; -} -pure_initcall(jit_init); - #ifdef CONFIG_PROC_FS void socket_seq_show(struct seq_file *seq) { diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 1f0687d8e3d7..799e65b944b9 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -340,14 +340,12 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) } static struct gss_upcall_msg * -__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth) +__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid) { struct gss_upcall_msg *pos; list_for_each_entry(pos, &pipe->in_downcall, list) { if (!uid_eq(pos->uid, uid)) continue; - if (auth && pos->auth->service != auth->service) - continue; atomic_inc(&pos->count); dprintk("RPC: %s found msg %p\n", __func__, pos); return pos; @@ -367,7 +365,7 @@ gss_add_msg(struct gss_upcall_msg *gss_msg) struct gss_upcall_msg *old; spin_lock(&pipe->lock); - old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth); + old = __gss_find_upcall(pipe, gss_msg->uid); if (old == NULL) { atomic_inc(&gss_msg->count); list_add(&gss_msg->list, &pipe->in_downcall); @@ -541,13 +539,9 @@ gss_setup_upcall(struct gss_auth *gss_auth, struct rpc_cred *cred) return gss_new; gss_msg = gss_add_msg(gss_new); if (gss_msg == gss_new) { - int res; - atomic_inc(&gss_msg->count); - res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg); + int res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg); if (res) { gss_unhash_msg(gss_new); - atomic_dec(&gss_msg->count); - gss_release_msg(gss_new); gss_msg = ERR_PTR(res); } } else @@ -720,7 +714,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) err = -ENOENT; /* Find a matching upcall */ spin_lock(&pipe->lock); - gss_msg = __gss_find_upcall(pipe, uid, NULL); + gss_msg = __gss_find_upcall(pipe, uid); if (gss_msg == NULL) { spin_unlock(&pipe->lock); goto err_put_ctx; @@ -840,7 +834,6 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) warn_gssd(); gss_release_msg(gss_msg); } - gss_release_msg(gss_msg); } static void gss_pipe_dentry_destroy(struct dentry *dir, diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c index 89731c9023f0..eeeba5adee6d 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c @@ -231,7 +231,6 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr, goto out_free_groups; GROUP_AT(creds->cr_group_info, i) = kgid; } - groups_sort(creds->cr_group_info); return 0; out_free_groups: @@ -261,7 +260,7 @@ static int gssx_dec_option_array(struct xdr_stream *xdr, if (!oa->data) return -ENOMEM; - creds = kzalloc(sizeof(struct svc_cred), GFP_KERNEL); + creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL); if (!creds) { kfree(oa->data); return -ENOMEM; diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 036bbf2b44c1..4605dc73def6 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -481,7 +481,6 @@ static int rsc_parse(struct cache_detail *cd, goto out; GROUP_AT(rsci.cred.cr_group_info, i) = kgid; } - groups_sort(rsci.cred.cr_group_info); /* mech name */ len = qword_get(&mesg, buf, mlen); @@ -1482,7 +1481,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) case RPC_GSS_PROC_DESTROY: if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) goto auth_err; - rsci->h.expiry_time = seconds_since_boot(); + rsci->h.expiry_time = get_seconds(); set_bit(CACHE_NEGATIVE, &rsci->h.flags); if (resv->iov_len + 4 > PAGE_SIZE) goto drop; diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index f28aeb2cfd32..23608eb0ded2 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -337,11 +337,6 @@ static int rpc_client_register(struct rpc_clnt *clnt, static DEFINE_IDA(rpc_clids); -void rpc_cleanup_clids(void) -{ - ida_destroy(&rpc_clids); -} - static int rpc_alloc_clid(struct rpc_clnt *clnt) { int clid; @@ -447,7 +442,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, return ERR_PTR(err); } -static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, +struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, struct rpc_xprt *xprt) { struct rpc_clnt *clnt = NULL; @@ -479,6 +474,7 @@ static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, return clnt; } +EXPORT_SYMBOL_GPL(rpc_create_xprt); /** * rpc_create - create an RPC client and transport with one call @@ -504,15 +500,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) }; char servername[48]; - if (args->bc_xprt) { - WARN_ON(args->protocol != XPRT_TRANSPORT_BC_TCP); - xprt = args->bc_xprt->xpt_bc_xprt; - if (xprt) { - xprt_get(xprt); - return rpc_create_xprt(args, xprt); - } - } - if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS) xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS; if (args->flags & RPC_CLNT_CREATE_NO_IDLE_TIMEOUT) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 9103dd15511c..d81186d34558 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -1375,7 +1375,6 @@ rpc_gssd_dummy_depopulate(struct dentry *pipe_dentry) struct dentry *clnt_dir = pipe_dentry->d_parent; struct dentry *gssd_dir = clnt_dir->d_parent; - dget(pipe_dentry); __rpc_rmpipe(d_inode(clnt_dir), pipe_dentry); __rpc_depopulate(clnt_dir, gssd_dummy_info_file, 0, 1); __rpc_depopulate(gssd_dir, gssd_dummy_clnt_dir, 0, 1); diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 1cb35c753dcd..73ad57a59989 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -273,9 +273,10 @@ static inline void rpc_task_set_debuginfo(struct rpc_task *task) static void rpc_set_active(struct rpc_task *task) { + trace_rpc_task_begin(task->tk_client, task, NULL); + rpc_task_set_debuginfo(task); set_bit(RPC_TASK_ACTIVE, &task->tk_runstate); - trace_rpc_task_begin(task->tk_client, task, NULL); } /* diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 3142f38d1104..ee5d3d253102 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -119,7 +119,6 @@ init_sunrpc(void) static void __exit cleanup_sunrpc(void) { - rpc_cleanup_clids(); rpcauth_remove_module(); cleanup_socket_xprt(); svc_cleanup_xprt_sock(); diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index c5b0cb4f4056..cc9852897395 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1188,17 +1188,11 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) *statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); /* Encode reply */ - if (*statp == rpc_drop_reply || - test_bit(RQ_DROPME, &rqstp->rq_flags)) { + if (test_bit(RQ_DROPME, &rqstp->rq_flags)) { if (procp->pc_release) procp->pc_release(rqstp, NULL, rqstp->rq_resp); goto dropit; } - if (*statp == rpc_autherr_badcred) { - if (procp->pc_release) - procp->pc_release(rqstp, NULL, rqstp->rq_resp); - goto err_bad_auth; - } if (*statp == rpc_success && (xdr = procp->pc_encode) && !xdr(rqstp, resv->iov_base+resv->iov_len, rqstp->rq_resp)) { diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 98db1715cb17..621ca7b4a155 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -520,7 +520,6 @@ static int unix_gid_parse(struct cache_detail *cd, GROUP_AT(ug.gi, i) = kgid; } - groups_sort(ug.gi); ugp = unix_gid_lookup(cd, uid); if (ugp) { struct cache_head *ch; @@ -828,7 +827,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv)); GROUP_AT(cred->cr_group_info, i) = kgid; } - groups_sort(cred->cr_group_info); if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { *authp = rpc_autherr_badverf; return SVC_DENIED; diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index d4e0d648bcea..ff4f01e527ec 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -346,6 +346,8 @@ int rdma_read_chunk_frmr(struct svcxprt_rdma *xprt, atomic_inc(&rdma_stat_read); return ret; err: + ib_dma_unmap_sg(xprt->sc_cm_id->device, + frmr->sg, frmr->sg_nents, frmr->direction); svc_rdma_put_context(ctxt, 0); svc_rdma_put_frmr(xprt, frmr); return ret; diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index c9c0976d3bbb..027c9ef8a263 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -474,16 +474,7 @@ static int xs_nospace(struct rpc_task *task) spin_unlock_bh(&xprt->transport_lock); /* Race breaker in case memory is freed before above code is called */ - if (ret == -EAGAIN) { - struct socket_wq *wq; - - rcu_read_lock(); - wq = rcu_dereference(sk->sk_wq); - set_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags); - rcu_read_unlock(); - - sk->sk_write_space(sk); - } + sk->sk_write_space(sk); return ret; } @@ -2295,10 +2286,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) /* SYN_SENT! */ if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO) xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; - break; - case -EADDRNOTAVAIL: - /* Source port number is unavailable. Try a new one! */ - transport->srcport = 0; } out: return ret; @@ -2360,15 +2347,9 @@ static void xs_tcp_setup_socket(struct work_struct *work) case -ECONNREFUSED: case -ECONNRESET: case -ENETUNREACH: - case -EHOSTUNREACH: case -EADDRINUSE: case -ENOBUFS: - /* - * xs_tcp_force_close() wakes tasks with -EIO. - * We need to wake them first to ensure the - * correct error code. - */ - xprt_wake_pending_tasks(xprt, status); + /* retry with existing socket, after a delay */ xs_tcp_force_close(xprt); goto out; } diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 1b58866175e6..d5d7132ac847 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -1169,7 +1169,6 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi, .obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB, .dst = dst, .dst_len = dst_len, - .fi = fi, .tos = tos, .type = type, .nlflags = nlflags, @@ -1178,6 +1177,8 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi, struct net_device *dev; int err = 0; + memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi)); + /* Don't offload route if using custom ip rules or if * IPv4 FIB offloading has been disabled completely. */ @@ -1221,7 +1222,6 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi, .obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB, .dst = dst, .dst_len = dst_len, - .fi = fi, .tos = tos, .type = type, .nlflags = 0, @@ -1230,6 +1230,8 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi, struct net_device *dev; int err = 0; + memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi)); + if (!(fi->fib_flags & RTNH_F_OFFLOAD)) return 0; diff --git a/net/sysctl_net.c b/net/sysctl_net.c index 46a71c701e7c..ed98c1fc3de1 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c @@ -46,7 +46,7 @@ static int net_ctl_permissions(struct ctl_table_header *head, kgid_t root_gid = make_kgid(net->user_ns, 0); /* Allow network administrator to have same access as root. */ - if (ns_capable_noaudit(net->user_ns, CAP_NET_ADMIN) || + if (ns_capable(net->user_ns, CAP_NET_ADMIN) || uid_eq(root_uid, current_euid())) { int mode = (table->mode >> 6) & 7; return (mode << 6) | (mode << 3) | mode; diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index cb1381513c82..648f2a67f314 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -381,10 +381,6 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, dev = dev_get_by_name(net, driver_name); if (!dev) return -ENODEV; - if (tipc_mtu_bad(dev, 0)) { - dev_put(dev); - return -EINVAL; - } /* Associate TIPC bearer with L2 bearer */ rcu_assign_pointer(b->media_ptr, dev); @@ -574,19 +570,14 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, if (!b_ptr) return NOTIFY_DONE; + b_ptr->mtu = dev->mtu; + switch (evt) { case NETDEV_CHANGE: if (netif_carrier_ok(dev)) break; case NETDEV_GOING_DOWN: - tipc_reset_bearer(net, b_ptr); - break; case NETDEV_CHANGEMTU: - if (tipc_mtu_bad(dev, 0)) { - bearer_disable(net, b_ptr); - break; - } - b_ptr->mtu = dev->mtu; tipc_reset_bearer(net, b_ptr); break; case NETDEV_CHANGEADDR: diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 5f11e18b1fa1..552185bc4773 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -39,7 +39,6 @@ #include "netlink.h" #include "core.h" -#include "msg.h" #include #define MAX_MEDIA 3 @@ -62,9 +61,6 @@ #define TIPC_MEDIA_TYPE_IB 2 #define TIPC_MEDIA_TYPE_UDP 3 -/* minimum bearer MTU */ -#define TIPC_MIN_BEARER_MTU (MAX_H_SIZE + INT_H_SIZE) - /** * struct tipc_node_map - set of node identifiers * @count: # of nodes in set @@ -230,13 +226,4 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, struct sk_buff_head *xmitq); -/* check if device MTU is too low for tipc headers */ -static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve) -{ - if (dev->mtu >= TIPC_MIN_BEARER_MTU + reserve) - return false; - netdev_warn(dev, "MTU too low for tipc bearer\n"); - return true; -} - #endif /* _TIPC_BEARER_H */ diff --git a/net/tipc/core.c b/net/tipc/core.c index e2bdb07a49a2..03a842870c52 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -69,7 +69,6 @@ static int __net_init tipc_init_net(struct net *net) if (err) goto out_nametbl; - INIT_LIST_HEAD(&tn->dist_queue); err = tipc_topsrv_start(net); if (err) goto out_subscr; diff --git a/net/tipc/core.h b/net/tipc/core.h index fe3b89e9cde4..18e95a8020cd 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -103,9 +103,6 @@ struct tipc_net { spinlock_t nametbl_lock; struct name_table *nametbl; - /* Name dist queue */ - struct list_head dist_queue; - /* Topology subscription server */ struct tipc_server *topsrv; atomic_t subscription_count; diff --git a/net/tipc/link.c b/net/tipc/link.c index 736fffb28ab6..91aea071ab27 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1084,6 +1084,25 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb, return rc; } +/* + * Send protocol message to the other endpoint. + */ +void tipc_link_proto_xmit(struct tipc_link *l, u32 msg_typ, int probe_msg, + u32 gap, u32 tolerance, u32 priority) +{ + struct sk_buff *skb = NULL; + struct sk_buff_head xmitq; + + __skb_queue_head_init(&xmitq); + tipc_link_build_proto_msg(l, msg_typ, probe_msg, gap, + tolerance, priority, &xmitq); + skb = __skb_dequeue(&xmitq); + if (!skb) + return; + tipc_bearer_xmit_skb(l->net, l->bearer_id, skb, l->media_addr); + l->rcv_unacked = 0; +} + static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, u16 rcvgap, int tolerance, int priority, struct sk_buff_head *xmitq) @@ -1243,8 +1262,6 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, /* fall thru' */ case ACTIVATE_MSG: - skb_linearize(skb); - hdr = buf_msg(skb); /* Complete own link name with peer's interface name */ if_name = strrchr(l->name, ':') + 1; @@ -1617,12 +1634,9 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) char *name; struct tipc_link *link; struct tipc_node *node; - struct sk_buff_head xmitq; struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; struct net *net = sock_net(skb->sk); - __skb_queue_head_init(&xmitq); - if (!info->attrs[TIPC_NLA_LINK]) return -EINVAL; @@ -1667,14 +1681,14 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]); link->tolerance = tol; - tipc_link_build_proto_msg(link, STATE_MSG, 0, 0, tol, 0, &xmitq); + tipc_link_proto_xmit(link, STATE_MSG, 0, 0, tol, 0); } if (props[TIPC_NLA_PROP_PRIO]) { u32 prio; prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]); link->priority = prio; - tipc_link_build_proto_msg(link, STATE_MSG, 0, 0, 0, prio, &xmitq); + tipc_link_proto_xmit(link, STATE_MSG, 0, 0, 0, prio); } if (props[TIPC_NLA_PROP_WIN]) { u32 win; @@ -1686,7 +1700,7 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) out: tipc_node_unlock(node); - tipc_bearer_xmit(net, bearer_id, &xmitq, &node->links[bearer_id].maddr); + return res; } diff --git a/net/tipc/link.h b/net/tipc/link.h index 2a0d58671e88..66d859b66c84 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -153,6 +153,7 @@ struct tipc_stats { struct tipc_link { u32 addr; char name[TIPC_MAX_LINK_NAME]; + struct tipc_media_addr *media_addr; struct net *net; /* Management and link supervision data */ diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 67bddcb2ff46..8740930f0787 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -541,7 +541,7 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err) return false; if (msg_errcode(msg)) return false; - *err = TIPC_ERR_NO_NAME; + *err = -TIPC_ERR_NO_NAME; if (skb_linearize(skb)) return false; msg = buf_msg(skb); diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index c4c151bc000c..c07612bab95c 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -40,6 +40,11 @@ int sysctl_tipc_named_timeout __read_mostly = 2000; +/** + * struct tipc_dist_queue - queue holding deferred name table updates + */ +static struct list_head tipc_dist_queue = LIST_HEAD_INIT(tipc_dist_queue); + struct distr_queue_item { struct distr_item i; u32 dtype; @@ -62,8 +67,6 @@ static void publ_to_item(struct distr_item *i, struct publication *p) /** * named_prepare_buf - allocate & initialize a publication message - * - * The buffer returned is of size INT_H_SIZE + payload size */ static struct sk_buff *named_prepare_buf(struct net *net, u32 type, u32 size, u32 dest) @@ -168,9 +171,9 @@ static void named_distribute(struct net *net, struct sk_buff_head *list, struct publication *publ; struct sk_buff *skb = NULL; struct distr_item *item = NULL; - u32 msg_dsz = ((tipc_node_get_mtu(net, dnode, 0) - INT_H_SIZE) / - ITEM_SIZE) * ITEM_SIZE; - u32 msg_rem = msg_dsz; + uint msg_dsz = (tipc_node_get_mtu(net, dnode, 0) / ITEM_SIZE) * + ITEM_SIZE; + uint msg_rem = msg_dsz; list_for_each_entry(publ, pls, local_list) { /* Prepare next buffer: */ @@ -337,11 +340,9 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i, * tipc_named_add_backlog - add a failed name table update to the backlog * */ -static void tipc_named_add_backlog(struct net *net, struct distr_item *i, - u32 type, u32 node) +static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node) { struct distr_queue_item *e; - struct tipc_net *tn = net_generic(net, tipc_net_id); unsigned long now = get_jiffies_64(); e = kzalloc(sizeof(*e), GFP_ATOMIC); @@ -351,7 +352,7 @@ static void tipc_named_add_backlog(struct net *net, struct distr_item *i, e->node = node; e->expires = now + msecs_to_jiffies(sysctl_tipc_named_timeout); memcpy(e, i, sizeof(*i)); - list_add_tail(&e->next, &tn->dist_queue); + list_add_tail(&e->next, &tipc_dist_queue); } /** @@ -361,11 +362,10 @@ static void tipc_named_add_backlog(struct net *net, struct distr_item *i, void tipc_named_process_backlog(struct net *net) { struct distr_queue_item *e, *tmp; - struct tipc_net *tn = net_generic(net, tipc_net_id); char addr[16]; unsigned long now = get_jiffies_64(); - list_for_each_entry_safe(e, tmp, &tn->dist_queue, next) { + list_for_each_entry_safe(e, tmp, &tipc_dist_queue, next) { if (time_after(e->expires, now)) { if (!tipc_update_nametbl(net, &e->i, e->node, e->dtype)) continue; @@ -397,7 +397,6 @@ void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq) spin_lock_bh(&tn->nametbl_lock); for (skb = skb_dequeue(inputq); skb; skb = skb_dequeue(inputq)) { - skb_linearize(skb); msg = buf_msg(skb); mtype = msg_type(msg); item = (struct distr_item *)msg_data(msg); @@ -405,7 +404,7 @@ void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq) node = msg_orignode(msg); while (count--) { if (!tipc_update_nametbl(net, item, node, mtype)) - tipc_named_add_backlog(net, item, mtype, node); + tipc_named_add_backlog(item, mtype, node); item++; } kfree_skb(skb); diff --git a/net/tipc/net.c b/net/tipc/net.c index 2763bd369b79..77bf9113c7a7 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -44,8 +44,7 @@ static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = { [TIPC_NLA_NET_UNSPEC] = { .type = NLA_UNSPEC }, - [TIPC_NLA_NET_ID] = { .type = NLA_U32 }, - [TIPC_NLA_NET_ADDR] = { .type = NLA_U32 }, + [TIPC_NLA_NET_ID] = { .type = NLA_U32 } }; /* diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index f86c6555a539..1eadc95e1132 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -258,15 +258,13 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, arg = nlmsg_new(0, GFP_KERNEL); if (!arg) { kfree_skb(msg->rep); - msg->rep = NULL; return -ENOMEM; } err = __tipc_nl_compat_dumpit(cmd, msg, arg); - if (err) { + if (err) kfree_skb(msg->rep); - msg->rep = NULL; - } + kfree_skb(arg); return err; @@ -576,8 +574,7 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg, link_info.dest = nla_get_flag(link[TIPC_NLA_LINK_DEST]); link_info.up = htonl(nla_get_flag(link[TIPC_NLA_LINK_UP])); - nla_strlcpy(link_info.str, link[TIPC_NLA_LINK_NAME], - TIPC_MAX_LINK_NAME); + strcpy(link_info.str, nla_data(link[TIPC_NLA_LINK_NAME])); return tipc_add_tlv(msg->rep, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); @@ -805,7 +802,7 @@ static int tipc_nl_compat_name_table_dump(struct tipc_nl_compat_msg *msg, goto out; tipc_tlv_sprintf(msg->rep, "%-10u %s", - nla_get_u32(publ[TIPC_NLA_PUBL_KEY]), + nla_get_u32(publ[TIPC_NLA_PUBL_REF]), scope_str[nla_get_u32(publ[TIPC_NLA_PUBL_SCOPE])]); out: tipc_tlv_sprintf(msg->rep, "\n"); diff --git a/net/tipc/node.c b/net/tipc/node.c index 2df0b98d4a32..3926b561f873 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -102,10 +102,9 @@ static unsigned int tipc_hashfn(u32 addr) static void tipc_node_kref_release(struct kref *kref) { - struct tipc_node *n = container_of(kref, struct tipc_node, kref); + struct tipc_node *node = container_of(kref, struct tipc_node, kref); - kfree(n->bc_entry.link); - kfree_rcu(n, rcu); + tipc_node_delete(node); } void tipc_node_put(struct tipc_node *node) @@ -217,20 +216,21 @@ static void tipc_node_delete(struct tipc_node *node) { list_del_rcu(&node->list); hlist_del_rcu(&node->hash); - tipc_node_put(node); - - del_timer_sync(&node->timer); - tipc_node_put(node); + kfree(node->bc_entry.link); + kfree_rcu(node, rcu); } void tipc_node_stop(struct net *net) { - struct tipc_net *tn = tipc_net(net); + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_node *node, *t_node; spin_lock_bh(&tn->node_list_lock); - list_for_each_entry_safe(node, t_node, &tn->node_list, list) - tipc_node_delete(node); + list_for_each_entry_safe(node, t_node, &tn->node_list, list) { + if (del_timer(&node->timer)) + tipc_node_put(node); + tipc_node_put(node); + } spin_unlock_bh(&tn->node_list_lock); } @@ -313,7 +313,9 @@ static void tipc_node_timeout(unsigned long data) if (rc & TIPC_LINK_DOWN_EVT) tipc_node_link_down(n, bearer_id, false); } - mod_timer(&n->timer, jiffies + n->keepalive_intv); + if (!mod_timer(&n->timer, jiffies + n->keepalive_intv)) + tipc_node_get(n); + tipc_node_put(n); } /** @@ -728,7 +730,7 @@ static void tipc_node_fsm_evt(struct tipc_node *n, int evt) state = SELF_UP_PEER_UP; break; case SELF_LOST_CONTACT_EVT: - state = SELF_DOWN_PEER_DOWN; + state = SELF_DOWN_PEER_LEAVING; break; case SELF_ESTABL_CONTACT_EVT: case PEER_LOST_CONTACT_EVT: @@ -747,7 +749,7 @@ static void tipc_node_fsm_evt(struct tipc_node *n, int evt) state = SELF_UP_PEER_UP; break; case PEER_LOST_CONTACT_EVT: - state = SELF_DOWN_PEER_DOWN; + state = SELF_LEAVING_PEER_DOWN; break; case SELF_LOST_CONTACT_EVT: case PEER_ESTABL_CONTACT_EVT: diff --git a/net/tipc/server.c b/net/tipc/server.c index f351863076c2..922e04a43396 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c @@ -311,7 +311,6 @@ static int tipc_accept_from_sock(struct tipc_conn *con) newcon->usr_data = s->tipc_conn_new(newcon->conid); if (!newcon->usr_data) { sock_release(newsock); - conn_put(newcon); return -ENOMEM; } @@ -453,11 +452,6 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid, if (!con) return -EINVAL; - if (!test_bit(CF_CONNECTED, &con->flags)) { - conn_put(con); - return 0; - } - e = tipc_alloc_entry(data, len); if (!e) { conn_put(con); @@ -471,8 +465,12 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid, list_add_tail(&e->list, &con->outqueue); spin_unlock_bh(&con->outqueue_lock); - if (!queue_work(s->send_wq, &con->swork)) + if (test_bit(CF_CONNECTED, &con->flags)) { + if (!queue_work(s->send_wq, &con->swork)) + conn_put(con); + } else { conn_put(con); + } return 0; } @@ -496,7 +494,7 @@ static void tipc_send_to_sock(struct tipc_conn *con) int ret; spin_lock_bh(&con->outqueue_lock); - while (test_bit(CF_CONNECTED, &con->flags)) { + while (1) { e = list_entry(con->outqueue.next, struct outqueue_entry, list); if ((struct list_head *) e == &con->outqueue) @@ -619,12 +617,14 @@ int tipc_server_start(struct tipc_server *s) void tipc_server_stop(struct tipc_server *s) { struct tipc_conn *con; + int total = 0; int id; spin_lock_bh(&s->idr_lock); - for (id = 0; s->idr_in_use; id++) { + for (id = 0; total < s->idr_in_use; id++) { con = idr_find(&s->conn_idr, id); if (con) { + total++; spin_unlock_bh(&s->idr_lock); tipc_close_conn(con); spin_lock_bh(&s->idr_lock); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 65171f8e8c45..e53003cf7703 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -777,11 +777,9 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, * @tsk: receiving socket * @skb: pointer to message buffer. */ -static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb, - struct sk_buff_head *xmitq) +static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb) { struct sock *sk = &tsk->sk; - u32 onode = tsk_own_node(tsk); struct tipc_msg *hdr = buf_msg(skb); int mtyp = msg_type(hdr); int conn_cong; @@ -794,8 +792,7 @@ static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb, if (mtyp == CONN_PROBE) { msg_set_type(hdr, CONN_PROBE_REPLY); - if (tipc_msg_reverse(onode, &skb, TIPC_OK)) - __skb_queue_tail(xmitq, skb); + tipc_sk_respond(sk, skb, TIPC_OK); return; } else if (mtyp == CONN_ACK) { conn_cong = tsk_conn_cong(tsk); @@ -1650,8 +1647,7 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf) * * Returns true if message was added to socket receive queue, otherwise false */ -static bool filter_rcv(struct sock *sk, struct sk_buff *skb, - struct sk_buff_head *xmitq) +static bool filter_rcv(struct sock *sk, struct sk_buff *skb) { struct socket *sock = sk->sk_socket; struct tipc_sock *tsk = tipc_sk(sk); @@ -1661,7 +1657,7 @@ static bool filter_rcv(struct sock *sk, struct sk_buff *skb, int usr = msg_user(hdr); if (unlikely(msg_user(hdr) == CONN_MANAGER)) { - tipc_sk_proto_rcv(tsk, skb, xmitq); + tipc_sk_proto_rcv(tsk, skb); return false; } @@ -1704,8 +1700,7 @@ static bool filter_rcv(struct sock *sk, struct sk_buff *skb, return true; reject: - if (tipc_msg_reverse(tsk_own_node(tsk), &skb, err)) - __skb_queue_tail(xmitq, skb); + tipc_sk_respond(sk, skb, err); return false; } @@ -1721,24 +1716,9 @@ static bool filter_rcv(struct sock *sk, struct sk_buff *skb, static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) { unsigned int truesize = skb->truesize; - struct sk_buff_head xmitq; - u32 dnode, selector; - __skb_queue_head_init(&xmitq); - - if (likely(filter_rcv(sk, skb, &xmitq))) { + if (likely(filter_rcv(sk, skb))) atomic_add(truesize, &tipc_sk(sk)->dupl_rcvcnt); - return 0; - } - - if (skb_queue_empty(&xmitq)) - return 0; - - /* Send response/rejected message */ - skb = __skb_dequeue(&xmitq); - dnode = msg_destnode(buf_msg(skb)); - selector = msg_origport(buf_msg(skb)); - tipc_node_xmit_skb(sock_net(sk), skb, dnode, selector); return 0; } @@ -1752,13 +1732,12 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) * Caller must hold socket lock */ static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk, - u32 dport, struct sk_buff_head *xmitq) + u32 dport) { - unsigned long time_limit = jiffies + 2; - struct sk_buff *skb; unsigned int lim; atomic_t *dcnt; - u32 onode; + struct sk_buff *skb; + unsigned long time_limit = jiffies + 2; while (skb_queue_len(inputq)) { if (unlikely(time_after_eq(jiffies, time_limit))) @@ -1770,22 +1749,20 @@ static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk, /* Add message directly to receive queue if possible */ if (!sock_owned_by_user(sk)) { - filter_rcv(sk, skb, xmitq); + filter_rcv(sk, skb); continue; } /* Try backlog, compensating for double-counted bytes */ dcnt = &tipc_sk(sk)->dupl_rcvcnt; - if (!sk->sk_backlog.len) + if (sk->sk_backlog.len) atomic_set(dcnt, 0); lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt); if (likely(!sk_add_backlog(sk, skb, lim))) continue; /* Overload => reject message back to sender */ - onode = tipc_own_addr(sock_net(sk)); - if (tipc_msg_reverse(onode, &skb, TIPC_ERR_OVERLOAD)) - __skb_queue_tail(xmitq, skb); + tipc_sk_respond(sk, skb, TIPC_ERR_OVERLOAD); break; } } @@ -1798,14 +1775,12 @@ static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk, */ void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq) { - struct sk_buff_head xmitq; u32 dnode, dport = 0; int err; struct tipc_sock *tsk; struct sock *sk; struct sk_buff *skb; - __skb_queue_head_init(&xmitq); while (skb_queue_len(inputq)) { dport = tipc_skb_peek_port(inputq, dport); tsk = tipc_sk_lookup(net, dport); @@ -1813,14 +1788,9 @@ void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq) if (likely(tsk)) { sk = &tsk->sk; if (likely(spin_trylock_bh(&sk->sk_lock.slock))) { - tipc_sk_enqueue(inputq, sk, dport, &xmitq); + tipc_sk_enqueue(inputq, sk, dport); spin_unlock_bh(&sk->sk_lock.slock); } - /* Send pending response/rejected messages, if any */ - while ((skb = __skb_dequeue(&xmitq))) { - dnode = msg_destnode(buf_msg(skb)); - tipc_node_xmit_skb(net, skb, dnode, dport); - } sock_put(sk); continue; } @@ -2141,8 +2111,7 @@ static int tipc_shutdown(struct socket *sock, int how) TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode, onode, dport, oport, TIPC_CONN_SHUTDOWN); - if (skb) - tipc_node_xmit_skb(net, skb, dnode, tsk->portid); + tipc_node_xmit_skb(net, skb, dnode, tsk->portid); } tsk->connected = 0; sock->state = SS_DISCONNECTING; @@ -2845,9 +2814,6 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb) if (err) return err; - if (!attrs[TIPC_NLA_SOCK]) - return -EINVAL; - err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, attrs[TIPC_NLA_SOCK], tipc_nl_sock_policy); diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index f9ff73a8d815..69ee2eeef968 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -296,8 +296,7 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid, if (tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscrb, &sub)) return tipc_conn_terminate(tn->topsrv, subscrb->conid); - if (sub) - tipc_nametbl_subscribe(sub); + tipc_nametbl_subscribe(sub); } /* Handle one request to establish a new subscriber */ diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index 78d6b78de29d..70c03271b798 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c @@ -48,11 +48,12 @@ #include #include "core.h" #include "bearer.h" +#include "msg.h" /* IANA assigned UDP port */ #define UDP_PORT_DEFAULT 6118 -#define UDP_MIN_HEADROOM 48 +#define UDP_MIN_HEADROOM 28 static const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = { [TIPC_NLA_UDP_UNSPEC] = {.type = NLA_UNSPEC}, @@ -223,6 +224,10 @@ static int tipc_udp_recv(struct sock *sk, struct sk_buff *skb) { struct udp_bearer *ub; struct tipc_bearer *b; + int usr = msg_user(buf_msg(skb)); + + if ((usr == LINK_PROTOCOL) || (usr == NAME_DISTRIBUTOR)) + skb_linearize(skb); ub = rcu_dereference_sk_user_data(sk); if (!ub) { @@ -376,11 +381,6 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, udp_conf.local_ip.s_addr = htonl(INADDR_ANY); udp_conf.use_udp_checksums = false; ub->ifindex = dev->ifindex; - if (tipc_mtu_bad(dev, sizeof(struct iphdr) + - sizeof(struct udphdr))) { - err = -EINVAL; - goto err; - } b->mtu = dev->mtu - sizeof(struct iphdr) - sizeof(struct udphdr); #if IS_ENABLED(CONFIG_IPV6) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index e05ec54ac53f..898a53a562b8 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -315,7 +315,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i) &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { struct dentry *dentry = unix_sk(s)->path.dentry; - if (dentry && d_real_inode(dentry) == i) { + if (dentry && d_backing_inode(dentry) == i) { sock_hold(s); goto found; } @@ -661,11 +661,11 @@ static int unix_set_peek_off(struct sock *sk, int val) { struct unix_sock *u = unix_sk(sk); - if (mutex_lock_interruptible(&u->iolock)) + if (mutex_lock_interruptible(&u->readlock)) return -EINTR; sk->sk_peek_off = val; - mutex_unlock(&u->iolock); + mutex_unlock(&u->readlock); return 0; } @@ -778,8 +778,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern) spin_lock_init(&u->lock); atomic_long_set(&u->inflight, 0); INIT_LIST_HEAD(&u->link); - mutex_init(&u->iolock); /* single task reading lock */ - mutex_init(&u->bindlock); /* single task binding lock */ + mutex_init(&u->readlock); /* single task reading lock */ init_waitqueue_head(&u->peer_wait); init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay); unix_insert_socket(unix_sockets_unbound(sk), sk); @@ -848,7 +847,7 @@ static int unix_autobind(struct socket *sock) int err; unsigned int retries = 0; - err = mutex_lock_interruptible(&u->bindlock); + err = mutex_lock_interruptible(&u->readlock); if (err) return err; @@ -895,7 +894,7 @@ static int unix_autobind(struct socket *sock) spin_unlock(&unix_table_lock); err = 0; -out: mutex_unlock(&u->bindlock); +out: mutex_unlock(&u->readlock); return err; } @@ -912,7 +911,7 @@ static struct sock *unix_find_other(struct net *net, err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path); if (err) goto fail; - inode = d_real_inode(path.dentry); + inode = d_backing_inode(path.dentry); err = inode_permission(inode, MAY_WRITE); if (err) goto put_fail; @@ -954,32 +953,20 @@ static struct sock *unix_find_other(struct net *net, return NULL; } -static int unix_mknod(const char *sun_path, umode_t mode, struct path *res) +static int unix_mknod(struct dentry *dentry, struct path *path, umode_t mode, + struct path *res) { - struct dentry *dentry; - struct path path; - int err = 0; - /* - * Get the parent directory, calculate the hash for last - * component. - */ - dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - return err; + int err; - /* - * All right, let's create it. - */ - err = security_path_mknod(&path, dentry, mode, 0); + err = security_path_mknod(path, dentry, mode, 0); if (!err) { - err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0); + err = vfs_mknod(d_inode(path->dentry), dentry, mode, 0); if (!err) { - res->mnt = mntget(path.mnt); + res->mnt = mntget(path->mnt); res->dentry = dget(dentry); } } - done_path_create(&path, dentry); + return err; } @@ -990,15 +977,15 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct unix_sock *u = unix_sk(sk); struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; char *sun_path = sunaddr->sun_path; - int err; + int err, name_err; unsigned int hash; struct unix_address *addr; struct hlist_head *list; - struct path path = { NULL, NULL }; + struct path path; + struct dentry *dentry; err = -EINVAL; - if (addr_len < offsetofend(struct sockaddr_un, sun_family) || - sunaddr->sun_family != AF_UNIX) + if (sunaddr->sun_family != AF_UNIX) goto out; if (addr_len == sizeof(short)) { @@ -1011,25 +998,34 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) goto out; addr_len = err; + name_err = 0; + dentry = NULL; if (sun_path[0]) { - umode_t mode = S_IFSOCK | - (SOCK_INODE(sock)->i_mode & ~current_umask()); - err = unix_mknod(sun_path, mode, &path); - if (err) { - if (err == -EEXIST) - err = -EADDRINUSE; - goto out; + /* Get the parent directory, calculate the hash for last + * component. + */ + dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); + + if (IS_ERR(dentry)) { + /* delay report until after 'already bound' check */ + name_err = PTR_ERR(dentry); + dentry = NULL; } } - err = mutex_lock_interruptible(&u->bindlock); + err = mutex_lock_interruptible(&u->readlock); if (err) - goto out_put; + goto out_path; err = -EINVAL; if (u->addr) goto out_up; + if (name_err) { + err = name_err == -EEXIST ? -EADDRINUSE : name_err; + goto out_up; + } + err = -ENOMEM; addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); if (!addr) @@ -1040,11 +1036,21 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) addr->hash = hash ^ sk->sk_type; atomic_set(&addr->refcnt, 1); - if (sun_path[0]) { + if (dentry) { + struct path u_path; + umode_t mode = S_IFSOCK | + (SOCK_INODE(sock)->i_mode & ~current_umask()); + err = unix_mknod(dentry, &path, mode, &u_path); + if (err) { + if (err == -EEXIST) + err = -EADDRINUSE; + unix_release_addr(addr); + goto out_up; + } addr->hash = UNIX_HASH_SIZE; - hash = d_real_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1); + hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1); spin_lock(&unix_table_lock); - u->path = path; + u->path = u_path; list = &unix_socket_table[hash]; } else { spin_lock(&unix_table_lock); @@ -1066,10 +1072,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) out_unlock: spin_unlock(&unix_table_lock); out_up: - mutex_unlock(&u->bindlock); -out_put: - if (err) - path_put(&path); + mutex_unlock(&u->readlock); +out_path: + if (dentry) + done_path_create(&path, dentry); + out: return err; } @@ -1109,10 +1116,6 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, unsigned int hash; int err; - err = -EINVAL; - if (alen < offsetofend(struct sockaddr, sa_family)) - goto out; - if (addr->sa_family != AF_UNSPEC) { err = unix_mkname(sunaddr, alen, &hash); if (err < 0) @@ -1968,17 +1971,17 @@ static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page, if (false) { alloc_skb: unix_state_unlock(other); - mutex_unlock(&unix_sk(other)->iolock); + mutex_unlock(&unix_sk(other)->readlock); newskb = sock_alloc_send_pskb(sk, 0, 0, flags & MSG_DONTWAIT, &err, 0); if (!newskb) goto err; } - /* we must acquire iolock as we modify already present + /* we must acquire readlock as we modify already present * skbs in the sk_receive_queue and mess with skb->len */ - err = mutex_lock_interruptible(&unix_sk(other)->iolock); + err = mutex_lock_interruptible(&unix_sk(other)->readlock); if (err) { err = flags & MSG_DONTWAIT ? -EAGAIN : -ERESTARTSYS; goto err; @@ -2045,7 +2048,7 @@ static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page, } unix_state_unlock(other); - mutex_unlock(&unix_sk(other)->iolock); + mutex_unlock(&unix_sk(other)->readlock); other->sk_data_ready(other); scm_destroy(&scm); @@ -2054,7 +2057,7 @@ static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page, err_state_unlock: unix_state_unlock(other); err_unlock: - mutex_unlock(&unix_sk(other)->iolock); + mutex_unlock(&unix_sk(other)->readlock); err: kfree_skb(newskb); if (send_sigpipe && !(flags & MSG_NOSIGNAL)) @@ -2119,7 +2122,7 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, if (flags&MSG_OOB) goto out; - err = mutex_lock_interruptible(&u->iolock); + err = mutex_lock_interruptible(&u->readlock); if (unlikely(err)) { /* recvmsg() in non blocking mode is supposed to return -EAGAIN * sk_rcvtimeo is not honored by mutex_lock_interruptible() @@ -2195,7 +2198,7 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, out_free: skb_free_datagram(sk, skb); out_unlock: - mutex_unlock(&u->iolock); + mutex_unlock(&u->readlock); out: return err; } @@ -2204,8 +2207,7 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, * Sleep until more data has arrived. But check for races.. */ static long unix_stream_data_wait(struct sock *sk, long timeo, - struct sk_buff *last, unsigned int last_len, - bool freezable) + struct sk_buff *last, unsigned int last_len) { struct sk_buff *tail; DEFINE_WAIT(wait); @@ -2226,10 +2228,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo, sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); unix_state_unlock(sk); - if (freezable) - timeo = freezable_schedule_timeout(timeo); - else - timeo = schedule_timeout(timeo); + timeo = freezable_schedule_timeout(timeo); unix_state_lock(sk); if (sock_flag(sk, SOCK_DEAD)) @@ -2259,8 +2258,7 @@ struct unix_stream_read_state { unsigned int splice_flags; }; -static int unix_stream_read_generic(struct unix_stream_read_state *state, - bool freezable) +static int unix_stream_read_generic(struct unix_stream_read_state *state) { struct scm_cookie scm; struct socket *sock = state->socket; @@ -2295,7 +2293,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state, /* Lock the socket to prevent queue disordering * while sleeps in memcpy_tomsg */ - mutex_lock(&u->iolock); + mutex_lock(&u->readlock); if (flags & MSG_PEEK) skip = sk_peek_offset(sk, flags); @@ -2336,10 +2334,10 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state, break; } - mutex_unlock(&u->iolock); + mutex_unlock(&u->readlock); timeo = unix_stream_data_wait(sk, timeo, last, - last_len, freezable); + last_len); if (signal_pending(current)) { err = sock_intr_errno(timeo); @@ -2347,7 +2345,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state, goto out; } - mutex_lock(&u->iolock); + mutex_lock(&u->readlock); continue; unlock: unix_state_unlock(sk); @@ -2450,7 +2448,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state, } } while (size); - mutex_unlock(&u->iolock); + mutex_unlock(&u->readlock); if (state->msg) scm_recv(sock, state->msg, &scm, flags); else @@ -2481,7 +2479,7 @@ static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, .flags = flags }; - return unix_stream_read_generic(&state, true); + return unix_stream_read_generic(&state); } static ssize_t skb_unix_socket_splice(struct sock *sk, @@ -2491,9 +2489,9 @@ static ssize_t skb_unix_socket_splice(struct sock *sk, int ret; struct unix_sock *u = unix_sk(sk); - mutex_unlock(&u->iolock); + mutex_unlock(&u->readlock); ret = splice_to_pipe(pipe, spd); - mutex_lock(&u->iolock); + mutex_lock(&u->readlock); return ret; } @@ -2527,7 +2525,7 @@ static ssize_t unix_stream_splice_read(struct socket *sock, loff_t *ppos, flags & SPLICE_F_NONBLOCK) state.flags = MSG_DONTWAIT; - return unix_stream_read_generic(&state, false); + return unix_stream_read_generic(&state); } static int unix_shutdown(struct socket *sock, int mode) diff --git a/net/unix/diag.c b/net/unix/diag.c index 384c84e83462..4d9679701a6d 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c @@ -257,8 +257,6 @@ static int unix_diag_get_exact(struct sk_buff *in_skb, err = -ENOENT; if (sk == NULL) goto out_nosk; - if (!net_eq(sock_net(sk), net)) - goto out; err = sock_diag_check_cookie(sk, req->udiag_cookie); if (err) diff --git a/net/unix/garbage.c b/net/unix/garbage.c index c36757e72844..6a0d48525fcf 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -146,7 +146,6 @@ void unix_notinflight(struct user_struct *user, struct file *fp) if (s) { struct unix_sock *u = unix_sk(s); - BUG_ON(!atomic_long_read(&u->inflight)); BUG_ON(list_empty(&u->link)); if (atomic_long_dec_and_test(&u->inflight)) @@ -342,14 +341,6 @@ void unix_gc(void) } list_del(&cursor); - /* Now gc_candidates contains only garbage. Restore original - * inflight counters for these as well, and remove the skbuffs - * which are creating the cycle(s). - */ - skb_queue_head_init(&hitlist); - list_for_each_entry(u, &gc_candidates, link) - scan_children(&u->sk, inc_inflight, &hitlist); - /* not_cycle_list contains those sockets which do not make up a * cycle. Restore these to the inflight list. */ @@ -359,6 +350,14 @@ void unix_gc(void) list_move_tail(&u->link, &gc_inflight_list); } + /* Now gc_candidates contains only garbage. Restore original + * inflight counters for these as well, and remove the skbuffs + * which are creating the cycle(s). + */ + skb_queue_head_init(&hitlist); + list_for_each_entry(u, &gc_candidates, link) + scan_children(&u->sk, inc_inflight, &hitlist); + spin_unlock(&unix_gc_lock); /* Here we are. Hitlist is filled. Die. */ diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 7f1d166ce612..9b5bd6d142dc 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -430,14 +430,14 @@ static int vsock_send_shutdown(struct sock *sk, int mode) return transport->shutdown(vsock_sk(sk), mode); } -static void vsock_pending_work(struct work_struct *work) +void vsock_pending_work(struct work_struct *work) { struct sock *sk; struct sock *listener; struct vsock_sock *vsk; bool cleanup; - vsk = container_of(work, struct vsock_sock, pending_work.work); + vsk = container_of(work, struct vsock_sock, dwork.work); sk = sk_vsock(vsk); listener = vsk->listener; cleanup = true; @@ -477,6 +477,7 @@ static void vsock_pending_work(struct work_struct *work) sock_put(sk); sock_put(listener); } +EXPORT_SYMBOL_GPL(vsock_pending_work); /**** SOCKET OPERATIONS ****/ @@ -575,8 +576,6 @@ static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr) return retval; } -static void vsock_connect_timeout(struct work_struct *work); - struct sock *__vsock_create(struct net *net, struct socket *sock, struct sock *parent, @@ -619,8 +618,6 @@ struct sock *__vsock_create(struct net *net, vsk->sent_request = false; vsk->ignore_connecting_rst = false; vsk->peer_shutdown = 0; - INIT_DELAYED_WORK(&vsk->connect_work, vsock_connect_timeout); - INIT_DELAYED_WORK(&vsk->pending_work, vsock_pending_work); psk = parent ? vsock_sk(parent) : NULL; if (parent) { @@ -1097,7 +1094,7 @@ static void vsock_connect_timeout(struct work_struct *work) struct sock *sk; struct vsock_sock *vsk; - vsk = container_of(work, struct vsock_sock, connect_work.work); + vsk = container_of(work, struct vsock_sock, dwork.work); sk = sk_vsock(vsk); lock_sock(sk); @@ -1198,7 +1195,9 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr, * timeout fires. */ sock_hold(sk); - schedule_delayed_work(&vsk->connect_work, timeout); + INIT_DELAYED_WORK(&vsk->dwork, + vsock_connect_timeout); + schedule_delayed_work(&vsk->dwork, timeout); /* Skip ahead to preserve error code set above. */ goto out_wait; @@ -1210,14 +1209,10 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr, if (signal_pending(current)) { err = sock_intr_errno(timeout); - sk->sk_state = SS_UNCONNECTED; - sock->state = SS_UNCONNECTED; - goto out_wait; + goto out_wait_error; } else if (timeout == 0) { err = -ETIMEDOUT; - sk->sk_state = SS_UNCONNECTED; - sock->state = SS_UNCONNECTED; - goto out_wait; + goto out_wait_error; } prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); @@ -1225,17 +1220,20 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr, if (sk->sk_err) { err = -sk->sk_err; - sk->sk_state = SS_UNCONNECTED; - sock->state = SS_UNCONNECTED; - } else { + goto out_wait_error; + } else err = 0; - } out_wait: finish_wait(sk_sleep(sk), &wait); out: release_sock(sk); return err; + +out_wait_error: + sk->sk_state = SS_UNCONNECTED; + sock->state = SS_UNCONNECTED; + goto out_wait; } static int vsock_accept(struct socket *sock, struct socket *newsock, int flags) @@ -1272,20 +1270,18 @@ static int vsock_accept(struct socket *sock, struct socket *newsock, int flags) listener->sk_err == 0) { release_sock(listener); timeout = schedule_timeout(timeout); - finish_wait(sk_sleep(listener), &wait); lock_sock(listener); if (signal_pending(current)) { err = sock_intr_errno(timeout); - goto out; + goto out_wait; } else if (timeout == 0) { err = -EAGAIN; - goto out; + goto out_wait; } prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE); } - finish_wait(sk_sleep(listener), &wait); if (listener->sk_err) err = -listener->sk_err; @@ -1305,15 +1301,19 @@ static int vsock_accept(struct socket *sock, struct socket *newsock, int flags) */ if (err) { vconnected->rejected = true; - } else { - newsock->state = SS_CONNECTED; - sock_graft(connected, newsock); + release_sock(connected); + sock_put(connected); + goto out_wait; } + newsock->state = SS_CONNECTED; + sock_graft(connected, newsock); release_sock(connected); sock_put(connected); } +out_wait: + finish_wait(sk_sleep(listener), &wait); out: release_sock(listener); return err; @@ -1513,7 +1513,8 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, long timeout; int err; struct vsock_transport_send_notify_data send_data; - DEFINE_WAIT_FUNC(wait, woken_wake_function); + + DEFINE_WAIT(wait); sk = sock->sk; vsk = vsock_sk(sk); @@ -1556,10 +1557,11 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, if (err < 0) goto out; + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); + while (total_written < len) { ssize_t written; - add_wait_queue(sk_sleep(sk), &wait); while (vsock_stream_has_space(vsk) == 0 && sk->sk_err == 0 && !(sk->sk_shutdown & SEND_SHUTDOWN) && @@ -1568,30 +1570,27 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, /* Don't wait for non-blocking sockets. */ if (timeout == 0) { err = -EAGAIN; - remove_wait_queue(sk_sleep(sk), &wait); - goto out_err; + goto out_wait; } err = transport->notify_send_pre_block(vsk, &send_data); - if (err < 0) { - remove_wait_queue(sk_sleep(sk), &wait); - goto out_err; - } + if (err < 0) + goto out_wait; release_sock(sk); - timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, timeout); + timeout = schedule_timeout(timeout); lock_sock(sk); if (signal_pending(current)) { err = sock_intr_errno(timeout); - remove_wait_queue(sk_sleep(sk), &wait); - goto out_err; + goto out_wait; } else if (timeout == 0) { err = -EAGAIN; - remove_wait_queue(sk_sleep(sk), &wait); - goto out_err; + goto out_wait; } + + prepare_to_wait(sk_sleep(sk), &wait, + TASK_INTERRUPTIBLE); } - remove_wait_queue(sk_sleep(sk), &wait); /* These checks occur both as part of and after the loop * conditional since we need to check before and after @@ -1599,16 +1598,16 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, */ if (sk->sk_err) { err = -sk->sk_err; - goto out_err; + goto out_wait; } else if ((sk->sk_shutdown & SEND_SHUTDOWN) || (vsk->peer_shutdown & RCV_SHUTDOWN)) { err = -EPIPE; - goto out_err; + goto out_wait; } err = transport->notify_send_pre_enqueue(vsk, &send_data); if (err < 0) - goto out_err; + goto out_wait; /* Note that enqueue will only write as many bytes as are free * in the produce queue, so we don't need to ensure len is @@ -1621,7 +1620,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, len - total_written); if (written < 0) { err = -ENOMEM; - goto out_err; + goto out_wait; } total_written += written; @@ -1629,13 +1628,14 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, err = transport->notify_send_post_enqueue( vsk, written, &send_data); if (err < 0) - goto out_err; + goto out_wait; } -out_err: +out_wait: if (total_written > 0) err = total_written; + finish_wait(sk_sleep(sk), &wait); out: release_sock(sk); return err; @@ -1716,61 +1716,21 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, if (err < 0) goto out; + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); while (1) { - s64 ready; - - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); - ready = vsock_stream_has_data(vsk); + s64 ready = vsock_stream_has_data(vsk); - if (ready == 0) { - if (sk->sk_err != 0 || - (sk->sk_shutdown & RCV_SHUTDOWN) || - (vsk->peer_shutdown & SEND_SHUTDOWN)) { - finish_wait(sk_sleep(sk), &wait); - break; - } - /* Don't wait for non-blocking sockets. */ - if (timeout == 0) { - err = -EAGAIN; - finish_wait(sk_sleep(sk), &wait); - break; - } - - err = transport->notify_recv_pre_block( - vsk, target, &recv_data); - if (err < 0) { - finish_wait(sk_sleep(sk), &wait); - break; - } - release_sock(sk); - timeout = schedule_timeout(timeout); - lock_sock(sk); + if (ready < 0) { + /* Invalid queue pair content. XXX This should be + * changed to a connection reset in a later change. + */ - if (signal_pending(current)) { - err = sock_intr_errno(timeout); - finish_wait(sk_sleep(sk), &wait); - break; - } else if (timeout == 0) { - err = -EAGAIN; - finish_wait(sk_sleep(sk), &wait); - break; - } - } else { + err = -ENOMEM; + goto out_wait; + } else if (ready > 0) { ssize_t read; - finish_wait(sk_sleep(sk), &wait); - - if (ready < 0) { - /* Invalid queue pair content. XXX This should - * be changed to a connection reset in a later - * change. - */ - - err = -ENOMEM; - goto out; - } - err = transport->notify_recv_pre_dequeue( vsk, target, &recv_data); if (err < 0) @@ -1790,12 +1750,42 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, vsk, target, read, !(flags & MSG_PEEK), &recv_data); if (err < 0) - goto out; + goto out_wait; if (read >= target || flags & MSG_PEEK) break; target -= read; + } else { + if (sk->sk_err != 0 || (sk->sk_shutdown & RCV_SHUTDOWN) + || (vsk->peer_shutdown & SEND_SHUTDOWN)) { + break; + } + /* Don't wait for non-blocking sockets. */ + if (timeout == 0) { + err = -EAGAIN; + break; + } + + err = transport->notify_recv_pre_block( + vsk, target, &recv_data); + if (err < 0) + break; + + release_sock(sk); + timeout = schedule_timeout(timeout); + lock_sock(sk); + + if (signal_pending(current)) { + err = sock_intr_errno(timeout); + break; + } else if (timeout == 0) { + err = -EAGAIN; + break; + } + + prepare_to_wait(sk_sleep(sk), &wait, + TASK_INTERRUPTIBLE); } } @@ -1807,6 +1797,8 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, if (copied > 0) err = copied; +out_wait: + finish_wait(sk_sleep(sk), &wait); out: release_sock(sk); return err; diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c index 589c8b9908a5..0a369bb440e7 100644 --- a/net/vmw_vsock/vmci_transport.c +++ b/net/vmw_vsock/vmci_transport.c @@ -842,7 +842,7 @@ static void vmci_transport_peer_detach_cb(u32 sub_id, * qp_handle. */ if (vmci_handle_is_invalid(e_payload->handle) || - !vmci_handle_is_equal(trans->qp_handle, e_payload->handle)) + vmci_handle_is_equal(trans->qp_handle, e_payload->handle)) return; /* We don't ask for delayed CBs when we subscribe to this event (we @@ -1099,7 +1099,8 @@ static int vmci_transport_recv_listen(struct sock *sk, vpending->listener = sk; sock_hold(sk); sock_hold(pending); - schedule_delayed_work(&vpending->pending_work, HZ); + INIT_DELAYED_WORK(&vpending->dwork, vsock_pending_work); + schedule_delayed_work(&vpending->dwork, HZ); out: return err; @@ -2153,7 +2154,7 @@ module_exit(vmci_transport_exit); MODULE_AUTHOR("VMware, Inc."); MODULE_DESCRIPTION("VMCI transport for Virtual Sockets"); -MODULE_VERSION("1.0.3.0-k"); +MODULE_VERSION("1.0.2.0-k"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("vmware_vsock"); MODULE_ALIAS_NETPROTO(PF_VSOCK); diff --git a/net/wireless/core.c b/net/wireless/core.c index a1e909ae0f78..8f0bac7e03c4 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -94,9 +94,6 @@ static int cfg80211_dev_check_name(struct cfg80211_registered_device *rdev, ASSERT_RTNL(); - if (strlen(newname) > NL80211_WIPHY_NAME_MAXLEN) - return -EINVAL; - /* prohibit calling the thing phy%d when %d is not its number */ sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) { @@ -393,8 +390,6 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, if (rv) goto use_default_name; } else { - int rv; - use_default_name: /* NOTE: This is *probably* safe w/out holding rtnl because of * the restrictions on phy names. Probably this call could @@ -402,11 +397,7 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, * phyX. But, might should add some locking and check return * value, and use a different name if this one exists? */ - rv = dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); - if (rv < 0) { - kfree(rdev); - return NULL; - } + dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); } INIT_LIST_HEAD(&rdev->wdev_list); diff --git a/net/wireless/core.h b/net/wireless/core.h index 47ea169aa0a3..a618b4b86fa4 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -72,7 +72,6 @@ struct cfg80211_registered_device { struct list_head bss_list; struct rb_root bss_tree; u32 bss_generation; - u32 bss_entries; struct cfg80211_scan_request *scan_req; /* protected by RTNL */ struct sk_buff *scan_msg; struct cfg80211_sched_scan_request __rcu *sched_scan_req; @@ -398,7 +397,6 @@ void cfg80211_sme_disassoc(struct wireless_dev *wdev); void cfg80211_sme_deauth(struct wireless_dev *wdev); void cfg80211_sme_auth_timeout(struct wireless_dev *wdev); void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev); -void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev); /* internal helpers */ bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher); diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index c0e02f72e931..fb44fa3bf4ef 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -149,18 +149,6 @@ void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss) } EXPORT_SYMBOL(cfg80211_assoc_timeout); -void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - - cfg80211_sme_abandon_assoc(wdev); - - cfg80211_unhold_bss(bss_from_pub(bss)); - cfg80211_put_bss(wiphy, bss); -} -EXPORT_SYMBOL(cfg80211_abandon_assoc); - void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len) { struct wireless_dev *wdev = dev->ieee80211_ptr; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b07fd8b8b50c..5d89f13a98db 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -303,7 +302,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, [NL80211_ATTR_PID] = { .type = NLA_U32 }, [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, - [NL80211_ATTR_PMKID] = { .len = WLAN_PMKID_LEN }, + [NL80211_ATTR_PMKID] = { .type = NLA_BINARY, + .len = WLAN_PMKID_LEN }, [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, @@ -359,7 +359,6 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, - [NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 }, [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 }, [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, @@ -486,14 +485,6 @@ nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = { [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 }, }; -/* policy for packet pattern attributes */ -static const struct nla_policy -nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = { - [NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, }, - [NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, }, - [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 }, -}; - static int nl80211_prepare_wdev_dump(struct sk_buff *skb, struct netlink_callback *cb, struct cfg80211_registered_device **rdev, @@ -501,17 +492,21 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, { int err; + rtnl_lock(); + if (!cb->args[0]) { err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, nl80211_fam.attrbuf, nl80211_fam.maxattr, nl80211_policy); if (err) - return err; + goto out_unlock; *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), nl80211_fam.attrbuf); - if (IS_ERR(*wdev)) - return PTR_ERR(*wdev); + if (IS_ERR(*wdev)) { + err = PTR_ERR(*wdev); + goto out_unlock; + } *rdev = wiphy_to_rdev((*wdev)->wiphy); /* 0 is the first index - add 1 to parse only once */ cb->args[0] = (*rdev)->wiphy_idx + 1; @@ -521,8 +516,10 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); struct wireless_dev *tmp; - if (!wiphy) - return -ENODEV; + if (!wiphy) { + err = -ENODEV; + goto out_unlock; + } *rdev = wiphy_to_rdev(wiphy); *wdev = NULL; @@ -533,11 +530,21 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, } } - if (!*wdev) - return -ENODEV; + if (!*wdev) { + err = -ENODEV; + goto out_unlock; + } } return 0; + out_unlock: + rtnl_unlock(); + return err; +} + +static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev) +{ + rtnl_unlock(); } /* IE validation */ @@ -1880,22 +1887,20 @@ static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { static int parse_txq_params(struct nlattr *tb[], struct ieee80211_txq_params *txq_params) { - u8 ac; - if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] || !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || !tb[NL80211_TXQ_ATTR_AIFS]) return -EINVAL; - ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]); + txq_params->ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]); txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); - if (ac >= NL80211_NUM_ACS) + if (txq_params->ac >= NL80211_NUM_ACS) return -EINVAL; - txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS); + return 0; } @@ -3578,7 +3583,6 @@ static int parse_station_flags(struct genl_info *info, params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) | BIT(NL80211_STA_FLAG_MFP) | BIT(NL80211_STA_FLAG_AUTHORIZED); - break; default: return -EINVAL; } @@ -3880,10 +3884,9 @@ static int nl80211_dump_station(struct sk_buff *skb, int sta_idx = cb->args[2]; int err; - rtnl_lock(); err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); if (err) - goto out_err; + return err; if (!wdev->netdev) { err = -EINVAL; @@ -3919,7 +3922,7 @@ static int nl80211_dump_station(struct sk_buff *skb, cb->args[2] = sta_idx; err = skb->len; out_err: - rtnl_unlock(); + nl80211_finish_wdev_dump(rdev); return err; } @@ -4636,10 +4639,9 @@ static int nl80211_dump_mpath(struct sk_buff *skb, int path_idx = cb->args[2]; int err; - rtnl_lock(); err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); if (err) - goto out_err; + return err; if (!rdev->ops->dump_mpath) { err = -EOPNOTSUPP; @@ -4673,7 +4675,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb, cb->args[2] = path_idx; err = skb->len; out_err: - rtnl_unlock(); + nl80211_finish_wdev_dump(rdev); return err; } @@ -4833,10 +4835,9 @@ static int nl80211_dump_mpp(struct sk_buff *skb, int path_idx = cb->args[2]; int err; - rtnl_lock(); err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); if (err) - goto out_err; + return err; if (!rdev->ops->dump_mpp) { err = -EOPNOTSUPP; @@ -4869,7 +4870,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb, cb->args[2] = path_idx; err = skb->len; out_err: - rtnl_unlock(); + nl80211_finish_wdev_dump(rdev); return err; } @@ -5717,10 +5718,6 @@ static int validate_scan_freqs(struct nlattr *freqs) struct nlattr *attr1, *attr2; int n_channels = 0, tmp1, tmp2; - nla_for_each_nested(attr1, freqs, tmp1) - if (nla_len(attr1) != sizeof(u32)) - return 0; - nla_for_each_nested(attr1, freqs, tmp1) { n_channels++; /* @@ -6631,7 +6628,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) params.n_counter_offsets_presp = len / sizeof(u16); if (rdev->wiphy.max_num_csa_counters && - (params.n_counter_offsets_presp > + (params.n_counter_offsets_beacon > rdev->wiphy.max_num_csa_counters)) return -EINVAL; @@ -6809,12 +6806,9 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) int start = cb->args[2], idx = 0; int err; - rtnl_lock(); err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); - if (err) { - rtnl_unlock(); + if (err) return err; - } wdev_lock(wdev); spin_lock_bh(&rdev->bss_lock); @@ -6837,7 +6831,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) wdev_unlock(wdev); cb->args[2] = idx; - rtnl_unlock(); + nl80211_finish_wdev_dump(rdev); return skb->len; } @@ -6921,10 +6915,9 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) int res; bool radio_stats; - rtnl_lock(); res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); if (res) - goto out_err; + return res; /* prepare_wdev_dump parsed the attributes */ radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS]; @@ -6965,7 +6958,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) cb->args[2] = survey_idx; res = skb->len; out_err: - rtnl_unlock(); + nl80211_finish_wdev_dump(rdev); return res; } @@ -9422,7 +9415,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) u8 *mask_pat; nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), - nla_len(pat), nl80211_packet_pattern_policy); + nla_len(pat), NULL); err = -EINVAL; if (!pat_tb[NL80211_PKTPAT_MASK] || !pat_tb[NL80211_PKTPAT_PATTERN]) @@ -9672,7 +9665,7 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev, u8 *mask_pat; nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), - nla_len(pat), nl80211_packet_pattern_policy); + nla_len(pat), NULL); if (!pat_tb[NL80211_PKTPAT_MASK] || !pat_tb[NL80211_PKTPAT_PATTERN]) return -EINVAL; @@ -9798,9 +9791,6 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) if (err) return err; - if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] || - !tb[NL80211_REKEY_DATA_KCK]) - return -EINVAL; if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN) return -ERANGE; if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN) @@ -10168,13 +10158,17 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, void *data = NULL; unsigned int data_len = 0; + rtnl_lock(); + if (cb->args[0]) { /* subtract the 1 again here */ struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); struct wireless_dev *tmp; - if (!wiphy) - return -ENODEV; + if (!wiphy) { + err = -ENODEV; + goto out_unlock; + } *rdev = wiphy_to_rdev(wiphy); *wdev = NULL; @@ -10195,11 +10189,13 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, nl80211_fam.attrbuf, nl80211_fam.maxattr, nl80211_policy); if (err) - return err; + goto out_unlock; if (!nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID] || - !nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) - return -EINVAL; + !nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) { + err = -EINVAL; + goto out_unlock; + } *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), nl80211_fam.attrbuf); @@ -10208,8 +10204,10 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), nl80211_fam.attrbuf); - if (IS_ERR(*rdev)) - return PTR_ERR(*rdev); + if (IS_ERR(*rdev)) { + err = PTR_ERR(*rdev); + goto out_unlock; + } vid = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID]); subcmd = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]); @@ -10222,15 +10220,19 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd) continue; - if (!vcmd->dumpit) - return -EOPNOTSUPP; + if (!vcmd->dumpit) { + err = -EOPNOTSUPP; + goto out_unlock; + } vcmd_idx = i; break; } - if (vcmd_idx < 0) - return -EOPNOTSUPP; + if (vcmd_idx < 0) { + err = -EOPNOTSUPP; + goto out_unlock; + } if (nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]) { data = nla_data(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]); @@ -10247,6 +10249,9 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, /* keep rtnl locked in successful case */ return 0; + out_unlock: + rtnl_unlock(); + return err; } static int nl80211_vendor_cmd_dump(struct sk_buff *skb, @@ -10261,10 +10266,9 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb, int err; struct nlattr *vendor_data; - rtnl_lock(); err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev); if (err) - goto out; + return err; vcmd_idx = cb->args[2]; data = (void *)cb->args[3]; @@ -10273,26 +10277,18 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb, if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV)) { - if (!wdev) { - err = -EINVAL; - goto out; - } + if (!wdev) + return -EINVAL; if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV && - !wdev->netdev) { - err = -EINVAL; - goto out; - } + !wdev->netdev) + return -EINVAL; if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) { if (wdev->netdev && - !netif_running(wdev->netdev)) { - err = -ENETDOWN; - goto out; - } - if (!wdev->netdev && !wdev->p2p_started) { - err = -ENETDOWN; - goto out; - } + !netif_running(wdev->netdev)) + return -ENETDOWN; + if (!wdev->netdev && !wdev->p2p_started) + return -ENETDOWN; } } @@ -13172,17 +13168,13 @@ static int nl80211_netlink_notify(struct notifier_block * nb, list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) { bool schedule_destroy_work = false; + bool schedule_scan_stop = false; struct cfg80211_sched_scan_request *sched_scan_req = rcu_dereference(rdev->sched_scan_req); if (sched_scan_req && notify->portid && - sched_scan_req->owner_nlportid == notify->portid) { - sched_scan_req->owner_nlportid = 0; - - if (rdev->ops->sched_scan_stop && - rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) - schedule_work(&rdev->sched_scan_stop_wk); - } + sched_scan_req->owner_nlportid == notify->portid) + schedule_scan_stop = true; list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) { cfg80211_mlme_unregister_socket(wdev, notify->portid); @@ -13213,6 +13205,12 @@ static int nl80211_netlink_notify(struct notifier_block * nb, spin_unlock(&rdev->destroy_list_lock); schedule_work(&rdev->destroy_work); } + } else if (schedule_scan_stop) { + sched_scan_req->owner_nlportid = 0; + + if (rdev->ops->sched_scan_stop && + rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) + schedule_work(&rdev->sched_scan_stop_wk); } } diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 6e7b86ca2abd..30f967665e84 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -56,19 +56,6 @@ * also linked into the probe response struct. */ -/* - * Limit the number of BSS entries stored in mac80211. Each one is - * a bit over 4k at most, so this limits to roughly 4-5M of memory. - * If somebody wants to really attack this though, they'd likely - * use small beacons, and only one type of frame, limiting each of - * the entries to a much smaller size (in order to generate more - * entries in total, so overhead is bigger.) - */ -static int bss_entries_limit = 1000; -module_param(bss_entries_limit, int, 0644); -MODULE_PARM_DESC(bss_entries_limit, - "limit to number of scan BSS entries (per wiphy, default 1000)"); - #define IEEE80211_SCAN_RESULT_EXPIRE (7 * HZ) static void bss_free(struct cfg80211_internal_bss *bss) @@ -149,10 +136,6 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev, list_del_init(&bss->list); rb_erase(&bss->rbn, &rdev->bss_tree); - rdev->bss_entries--; - WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list), - "rdev bss entries[%d]/list[empty:%d] corruption\n", - rdev->bss_entries, list_empty(&rdev->bss_list)); bss_ref_put(rdev, bss); return true; } @@ -179,40 +162,6 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *rdev, rdev->bss_generation++; } -static bool cfg80211_bss_expire_oldest(struct cfg80211_registered_device *rdev) -{ - struct cfg80211_internal_bss *bss, *oldest = NULL; - bool ret; - - lockdep_assert_held(&rdev->bss_lock); - - list_for_each_entry(bss, &rdev->bss_list, list) { - if (atomic_read(&bss->hold)) - continue; - - if (!list_empty(&bss->hidden_list) && - !bss->pub.hidden_beacon_bss) - continue; - - if (oldest && time_before(oldest->ts, bss->ts)) - continue; - oldest = bss; - } - - if (WARN_ON(!oldest)) - return false; - - /* - * The callers make sure to increase rdev->bss_generation if anything - * gets removed (and a new entry added), so there's no need to also do - * it here. - */ - - ret = __cfg80211_unlink_bss(rdev, oldest); - WARN_ON(!ret); - return ret; -} - void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool send_message) { @@ -738,7 +687,6 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev, const u8 *ie; int i, ssidlen; u8 fold = 0; - u32 n_entries = 0; ies = rcu_access_pointer(new->pub.beacon_ies); if (WARN_ON(!ies)) @@ -762,12 +710,6 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev, /* This is the bad part ... */ list_for_each_entry(bss, &rdev->bss_list, list) { - /* - * we're iterating all the entries anyway, so take the - * opportunity to validate the list length accounting - */ - n_entries++; - if (!ether_addr_equal(bss->pub.bssid, new->pub.bssid)) continue; if (bss->pub.channel != new->pub.channel) @@ -796,10 +738,6 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev, new->pub.beacon_ies); } - WARN_ONCE(n_entries != rdev->bss_entries, - "rdev bss entries[%d]/list[len:%d] corruption\n", - rdev->bss_entries, n_entries); - return true; } @@ -952,14 +890,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, } } - if (rdev->bss_entries >= bss_entries_limit && - !cfg80211_bss_expire_oldest(rdev)) { - kfree(new); - goto drop; - } - list_add_tail(&new->list, &rdev->bss_list); - rdev->bss_entries++; rb_insert_bss(rdev, new); found = new; } diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 18b4a652cf41..8020b5b094d4 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -39,7 +39,6 @@ struct cfg80211_conn { CFG80211_CONN_ASSOCIATING, CFG80211_CONN_ASSOC_FAILED, CFG80211_CONN_DEAUTH, - CFG80211_CONN_ABANDON, CFG80211_CONN_CONNECTED, } state; u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; @@ -205,8 +204,6 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, NULL, 0, WLAN_REASON_DEAUTH_LEAVING, false); - /* fall through */ - case CFG80211_CONN_ABANDON: /* free directly, disconnected event already sent */ cfg80211_sme_free(wdev); return 0; @@ -426,17 +423,6 @@ void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev) schedule_work(&rdev->conn_work); } -void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev) -{ - struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); - - if (!wdev->conn) - return; - - wdev->conn->state = CFG80211_CONN_ABANDON; - schedule_work(&rdev->conn_work); -} - static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev, const u8 *ies, size_t ies_len, const u8 **out_ies, size_t *out_ies_len) diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index c6ab4da4b8e2..a750f330b8dd 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1794,40 +1794,32 @@ void x25_kill_by_neigh(struct x25_neigh *nb) static int __init x25_init(void) { - int rc; + int rc = proto_register(&x25_proto, 0); - rc = proto_register(&x25_proto, 0); - if (rc) + if (rc != 0) goto out; rc = sock_register(&x25_family_ops); - if (rc) + if (rc != 0) goto out_proto; dev_add_pack(&x25_packet_type); rc = register_netdevice_notifier(&x25_dev_notifier); - if (rc) + if (rc != 0) goto out_sock; - rc = x25_register_sysctl(); - if (rc) - goto out_dev; - - rc = x25_proc_init(); - if (rc) - goto out_sysctl; - pr_info("Linux Version 0.2\n"); + x25_register_sysctl(); + rc = x25_proc_init(); + if (rc != 0) + goto out_dev; out: return rc; -out_sysctl: - x25_unregister_sysctl(); out_dev: unregister_netdevice_notifier(&x25_dev_notifier); out_sock: - dev_remove_pack(&x25_packet_type); sock_unregister(AF_X25); out_proto: proto_unregister(&x25_proto); diff --git a/net/x25/sysctl_net_x25.c b/net/x25/sysctl_net_x25.c index 703d46aae7a2..43239527a205 100644 --- a/net/x25/sysctl_net_x25.c +++ b/net/x25/sysctl_net_x25.c @@ -73,12 +73,9 @@ static struct ctl_table x25_table[] = { { 0, }, }; -int __init x25_register_sysctl(void) +void __init x25_register_sysctl(void) { x25_table_header = register_net_sysctl(&init_net, "net/x25", x25_table); - if (!x25_table_header) - return -ENOMEM; - return 0; } void x25_unregister_sysctl(void) diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c index a00ec715aa46..ccfdc7115a83 100644 --- a/net/xfrm/xfrm_ipcomp.c +++ b/net/xfrm/xfrm_ipcomp.c @@ -283,7 +283,7 @@ static struct crypto_comp * __percpu *ipcomp_alloc_tfms(const char *alg_name) struct crypto_comp *tfm; /* This can be any valid CPU ID so we don't need locking. */ - tfm = this_cpu_read(*pos->tfms); + tfm = __this_cpu_read(*pos->tfms); if (!strcmp(crypto_comp_name(tfm), alg_name)) { pos->users++; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index f3683c64d3d5..b9476c029041 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -626,11 +626,6 @@ static void xfrm_hash_rebuild(struct work_struct *work) /* re-insert all policies by order of creation */ list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) { - if (policy->walk.dead || - xfrm_policy_id2dir(policy->index) >= XFRM_POLICY_MAX) { - /* skip socket policies */ - continue; - } newpos = NULL; chain = policy_hash_bysel(net, &policy->selector, policy->family, @@ -1221,7 +1216,7 @@ static inline int policy_to_flow_dir(int dir) } static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir, - const struct flowi *fl, u16 family) + const struct flowi *fl) { struct xfrm_policy *pol; struct net *net = sock_net(sk); @@ -1230,15 +1225,10 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir, read_lock_bh(&net->xfrm.xfrm_policy_lock); pol = rcu_dereference(sk->sk_policy[dir]); if (pol != NULL) { - bool match; + bool match = xfrm_selector_match(&pol->selector, fl, + sk->sk_family); int err = 0; - if (pol->family != family) { - pol = NULL; - goto out; - } - - match = xfrm_selector_match(&pol->selector, fl, family); if (match) { if ((sk->sk_mark & pol->mark.m) != pol->mark.v) { pol = NULL; @@ -1318,7 +1308,7 @@ EXPORT_SYMBOL(xfrm_policy_delete); int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) { - struct net *net = sock_net(sk); + struct net *net = xp_net(pol); struct xfrm_policy *old_pol; #ifdef CONFIG_XFRM_SUB_POLICY @@ -1372,7 +1362,6 @@ static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir) newp->xfrm_nr = old->xfrm_nr; newp->index = old->index; newp->type = old->type; - newp->family = old->family; memcpy(newp->xfrm_vec, old->xfrm_vec, newp->xfrm_nr*sizeof(struct xfrm_tmpl)); write_lock_bh(&net->xfrm.xfrm_policy_lock); @@ -1787,6 +1776,43 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, goto out; } +#ifdef CONFIG_XFRM_SUB_POLICY +static int xfrm_dst_alloc_copy(void **target, const void *src, int size) +{ + if (!*target) { + *target = kmalloc(size, GFP_ATOMIC); + if (!*target) + return -ENOMEM; + } + + memcpy(*target, src, size); + return 0; +} +#endif + +static int xfrm_dst_update_parent(struct dst_entry *dst, + const struct xfrm_selector *sel) +{ +#ifdef CONFIG_XFRM_SUB_POLICY + struct xfrm_dst *xdst = (struct xfrm_dst *)dst; + return xfrm_dst_alloc_copy((void **)&(xdst->partner), + sel, sizeof(*sel)); +#else + return 0; +#endif +} + +static int xfrm_dst_update_origin(struct dst_entry *dst, + const struct flowi *fl) +{ +#ifdef CONFIG_XFRM_SUB_POLICY + struct xfrm_dst *xdst = (struct xfrm_dst *)dst; + return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl)); +#else + return 0; +#endif +} + static int xfrm_expand_policies(const struct flowi *fl, u16 family, struct xfrm_policy **pols, int *num_pols, int *num_xfrms) @@ -1858,6 +1884,16 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols, xdst = (struct xfrm_dst *)dst; xdst->num_xfrms = err; + if (num_pols > 1) + err = xfrm_dst_update_parent(dst, &pols[1]->selector); + else + err = xfrm_dst_update_origin(dst, fl); + if (unlikely(err)) { + dst_free(dst); + XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); + return ERR_PTR(err); + } + xdst->num_pols = num_pols; memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols); xdst->policy_genid = atomic_read(&pols[0]->genid); @@ -2185,7 +2221,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, sk = sk_const_to_full_sk(sk); if (sk && sk->sk_policy[XFRM_POLICY_OUT]) { num_pols = 1; - pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, family); + pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); err = xfrm_expand_policies(fl, family, pols, &num_pols, &num_xfrms); if (err < 0) @@ -2326,9 +2362,6 @@ struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE) return make_blackhole(net, dst_orig->ops->family, dst_orig); - if (IS_ERR(dst)) - dst_release(dst_orig); - return dst; } EXPORT_SYMBOL(xfrm_lookup_route); @@ -2467,7 +2500,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, pol = NULL; sk = sk_to_full_sk(sk); if (sk && sk->sk_policy[dir]) { - pol = xfrm_sk_policy_lookup(sk, dir, &fl, family); + pol = xfrm_sk_policy_lookup(sk, dir, &fl); if (IS_ERR(pol)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); return 0; @@ -2997,11 +3030,6 @@ static int __net_init xfrm_net_init(struct net *net) { int rv; - /* Initialize the per-net locks here */ - spin_lock_init(&net->xfrm.xfrm_state_lock); - rwlock_init(&net->xfrm.xfrm_policy_lock); - mutex_init(&net->xfrm.xfrm_cfg_mutex); - rv = xfrm_statistics_init(net); if (rv < 0) goto out_statistics; @@ -3018,6 +3046,11 @@ static int __net_init xfrm_net_init(struct net *net) if (rv < 0) goto out; + /* Initialize the per-net locks here */ + spin_lock_init(&net->xfrm.xfrm_state_lock); + rwlock_init(&net->xfrm.xfrm_policy_lock); + mutex_init(&net->xfrm.xfrm_cfg_mutex); + return 0; out: diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 443533a0ff99..2912e9bf9fa8 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1159,7 +1159,6 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig) if (orig->aead) { x->aead = xfrm_algo_aead_clone(orig->aead); - x->geniv = orig->geniv; if (!x->aead) goto error; } @@ -1209,8 +1208,6 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig) x->curlft.add_time = orig->curlft.add_time; x->km.state = orig->km.state; x->km.seq = orig->km.seq; - x->replay = orig->replay; - x->preplay = orig->preplay; return x; @@ -1848,18 +1845,6 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen struct xfrm_mgr *km; struct xfrm_policy *pol = NULL; -#ifdef CONFIG_COMPAT - if (is_compat_task()) - return -EOPNOTSUPP; -#endif - - if (!optval && !optlen) { - xfrm_sk_policy_insert(sk, XFRM_POLICY_IN, NULL); - xfrm_sk_policy_insert(sk, XFRM_POLICY_OUT, NULL); - __sk_dst_reset(sk); - return 0; - } - if (optlen <= 0 || optlen > PAGE_SIZE) return -EMSGSIZE; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index b0ab3ad9a00f..4f6054ca31ec 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -121,17 +121,22 @@ static inline int verify_replay(struct xfrm_usersa_info *p, struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; struct xfrm_replay_state_esn *rs; - if (!rt) - return (p->flags & XFRM_STATE_ESN) ? -EINVAL : 0; + if (p->flags & XFRM_STATE_ESN) { + if (!rt) + return -EINVAL; - rs = nla_data(rt); + rs = nla_data(rt); - if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8) - return -EINVAL; + if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8) + return -EINVAL; - if (nla_len(rt) < xfrm_replay_state_esn_len(rs) && - nla_len(rt) != sizeof(*rs)) - return -EINVAL; + if (nla_len(rt) < xfrm_replay_state_esn_len(rs) && + nla_len(rt) != sizeof(*rs)) + return -EINVAL; + } + + if (!rt) + return 0; /* As only ESP and AH support ESN feature. */ if ((p->id.proto != IPPROTO_ESP) && (p->id.proto != IPPROTO_AH)) @@ -980,12 +985,10 @@ static inline int xfrm_nlmsg_multicast(struct net *net, struct sk_buff *skb, { struct sock *nlsk = rcu_dereference(net->xfrm.nlsk); - if (!nlsk) { - kfree_skb(skb); - return -EPIPE; - } - - return nlmsg_multicast(nlsk, skb, pid, group, GFP_ATOMIC); + if (nlsk) + return nlmsg_multicast(nlsk, skb, pid, group, GFP_ATOMIC); + else + return -1; } static inline size_t xfrm_spdinfo_msgsize(void) @@ -1373,14 +1376,11 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) { - u16 prev_family; int i; if (nr > XFRM_MAX_DEPTH) return -EINVAL; - prev_family = family; - for (i = 0; i < nr; i++) { /* We never validated the ut->family value, so many * applications simply leave it at zero. The check was @@ -1392,12 +1392,6 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) if (!ut[i].family) ut[i].family = family; - if ((ut[i].mode == XFRM_MODE_TRANSPORT) && - (ut[i].family != prev_family)) - return -EINVAL; - - prev_family = ut[i].family; - switch (ut[i].family) { case AF_INET: break; @@ -1408,21 +1402,6 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) default: return -EINVAL; } - - switch (ut[i].id.proto) { - case IPPROTO_AH: - case IPPROTO_ESP: - case IPPROTO_COMP: -#if IS_ENABLED(CONFIG_IPV6) - case IPPROTO_ROUTING: - case IPPROTO_DSTOPTS: -#endif - case IPSEC_PROTO_ANY: - break; - default: - return -EINVAL; - } - } return 0; @@ -1626,11 +1605,9 @@ static inline size_t userpolicy_type_attrsize(void) #ifdef CONFIG_XFRM_SUB_POLICY static int copy_to_user_policy_type(u8 type, struct sk_buff *skb) { - struct xfrm_userpolicy_type upt; - - /* Sadly there are two holes in struct xfrm_userpolicy_type */ - memset(&upt, 0, sizeof(upt)); - upt.type = type; + struct xfrm_userpolicy_type upt = { + .type = type, + }; return nla_put(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt); } @@ -1675,34 +1652,32 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr static int xfrm_dump_policy_done(struct netlink_callback *cb) { - struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args; + struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; struct net *net = sock_net(cb->skb->sk); xfrm_policy_walk_done(walk, net); return 0; } -static int xfrm_dump_policy_start(struct netlink_callback *cb) -{ - struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args; - - BUILD_BUG_ON(sizeof(*walk) > sizeof(cb->args)); - - xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); - return 0; -} - static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); - struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args; + struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; struct xfrm_dump_info info; + BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) > + sizeof(cb->args) - sizeof(cb->args[0])); + info.in_skb = cb->skb; info.out_skb = skb; info.nlmsg_seq = cb->nlh->nlmsg_seq; info.nlmsg_flags = NLM_F_MULTI; + if (!cb->args[0]) { + cb->args[0] = 1; + xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); + } + (void) xfrm_policy_walk(net, walk, dump_one_policy, &info); return skb->len; @@ -2440,7 +2415,6 @@ static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = { static const struct xfrm_link { int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); - int (*start)(struct netlink_callback *); int (*dump)(struct sk_buff *, struct netlink_callback *); int (*done)(struct netlink_callback *); const struct nla_policy *nla_pol; @@ -2454,7 +2428,6 @@ static const struct xfrm_link { [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy }, [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, - .start = xfrm_dump_policy_start, .dump = xfrm_dump_policy, .done = xfrm_dump_policy_done }, [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, @@ -2484,7 +2457,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) #ifdef CONFIG_COMPAT if (is_compat_task()) - return -EOPNOTSUPP; + return -ENOTSUPP; #endif type = nlh->nlmsg_type; @@ -2506,7 +2479,6 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { struct netlink_dump_control c = { - .start = link->start, .dump = link->dump, .done = link->done, };