summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.c50
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c18
-rw-r--r--drivers/net/ethernet/ti/Kconfig2
-rw-r--r--drivers/net/ppp/ppp_generic.c5
-rw-r--r--drivers/s390/net/qeth_core.h4
-rw-r--r--drivers/s390/net/qeth_core_main.c158
-rw-r--r--drivers/s390/net/qeth_core_mpc.h14
-rw-r--r--drivers/s390/net/qeth_ethtool.c1
-rw-r--r--drivers/s390/net/qeth_l2_main.c12
-rw-r--r--drivers/s390/net/qeth_l3_main.c13
-rw-r--r--include/linux/skbuff.h2
-rw-r--r--net/core/skbuff.c4
-rw-r--r--net/hsr/hsr_device.c9
-rw-r--r--net/openvswitch/actions.c3
-rw-r--r--net/sched/act_mpls.c3
16 files changed, 170 insertions, 130 deletions
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 1e09fdb63c4f..c4f6ec0cd183 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -1115,7 +1115,7 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
phy_interface_mode(lmac->lmac_type)))
return -ENODEV;
- phy_start_aneg(lmac->phydev);
+ phy_start(lmac->phydev);
return 0;
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index ba0536802b13..69545dd6c938 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -1287,30 +1287,25 @@ static bool hns3_skb_need_linearized(struct sk_buff *skb, unsigned int *bd_size,
}
static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring,
- struct sk_buff **out_skb)
+ struct net_device *netdev,
+ struct sk_buff *skb)
{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
unsigned int bd_size[HNS3_MAX_TSO_BD_NUM + 1U];
- struct sk_buff *skb = *out_skb;
unsigned int bd_num;
bd_num = hns3_tx_bd_num(skb, bd_size);
if (unlikely(bd_num > HNS3_MAX_NON_TSO_BD_NUM)) {
- struct sk_buff *new_skb;
-
if (bd_num <= HNS3_MAX_TSO_BD_NUM && skb_is_gso(skb) &&
!hns3_skb_need_linearized(skb, bd_size, bd_num))
goto out;
- /* manual split the send packet */
- new_skb = skb_copy(skb, GFP_ATOMIC);
- if (!new_skb)
+ if (__skb_linearize(skb))
return -ENOMEM;
- dev_kfree_skb_any(skb);
- *out_skb = new_skb;
- bd_num = hns3_tx_bd_count(new_skb->len);
- if ((skb_is_gso(new_skb) && bd_num > HNS3_MAX_TSO_BD_NUM) ||
- (!skb_is_gso(new_skb) &&
+ bd_num = hns3_tx_bd_count(skb->len);
+ if ((skb_is_gso(skb) && bd_num > HNS3_MAX_TSO_BD_NUM) ||
+ (!skb_is_gso(skb) &&
bd_num > HNS3_MAX_NON_TSO_BD_NUM))
return -ENOMEM;
@@ -1320,10 +1315,23 @@ static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring,
}
out:
- if (unlikely(ring_space(ring) < bd_num))
- return -EBUSY;
+ if (likely(ring_space(ring) >= bd_num))
+ return bd_num;
- return bd_num;
+ netif_stop_subqueue(netdev, ring->queue_index);
+ smp_mb(); /* Memory barrier before checking ring_space */
+
+ /* Start queue in case hns3_clean_tx_ring has just made room
+ * available and has not seen the queue stopped state performed
+ * by netif_stop_subqueue above.
+ */
+ if (ring_space(ring) >= bd_num && netif_carrier_ok(netdev) &&
+ !test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) {
+ netif_start_subqueue(netdev, ring->queue_index);
+ return bd_num;
+ }
+
+ return -EBUSY;
}
static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig)
@@ -1400,13 +1408,13 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
/* Prefetch the data used later */
prefetch(skb->data);
- ret = hns3_nic_maybe_stop_tx(ring, &skb);
+ ret = hns3_nic_maybe_stop_tx(ring, netdev, skb);
if (unlikely(ret <= 0)) {
if (ret == -EBUSY) {
u64_stats_update_begin(&ring->syncp);
ring->stats.tx_busy++;
u64_stats_update_end(&ring->syncp);
- goto out_net_tx_busy;
+ return NETDEV_TX_BUSY;
} else if (ret == -ENOMEM) {
u64_stats_update_begin(&ring->syncp);
ring->stats.sw_err_cnt++;
@@ -1457,12 +1465,6 @@ fill_err:
out_err_tx_ok:
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
-
-out_net_tx_busy:
- netif_stop_subqueue(netdev, ring->queue_index);
- smp_mb(); /* Commit all data before submit */
-
- return NETDEV_TX_BUSY;
}
static int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p)
@@ -2519,7 +2521,7 @@ void hns3_clean_tx_ring(struct hns3_enet_ring *ring)
dev_queue = netdev_get_tx_queue(netdev, ring->tqp->tqp_index);
netdev_tx_completed_queue(dev_queue, pkts, bytes);
- if (unlikely(pkts && netif_carrier_ok(netdev) &&
+ if (unlikely(netif_carrier_ok(netdev) &&
ring_space(ring) > HNS3_MAX_TSO_BD_NUM)) {
/* Make sure that anybody stopping the queue after this
* sees the new next_to_clean.
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 7c7038676d6d..d862e9ba27e1 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -8438,13 +8438,16 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
if (hdev->pdev->revision == 0x20)
return -EOPNOTSUPP;
+ vport = hclge_get_vf_vport(hdev, vfid);
+ if (!vport)
+ return -EINVAL;
+
/* qos is a 3 bits value, so can not be bigger than 7 */
- if (vfid >= hdev->num_alloc_vfs || vlan > VLAN_N_VID - 1 || qos > 7)
+ if (vlan > VLAN_N_VID - 1 || qos > 7)
return -EINVAL;
if (proto != htons(ETH_P_8021Q))
return -EPROTONOSUPPORT;
- vport = &hdev->vport[vfid];
state = hclge_get_port_base_vlan_state(vport,
vport->port_base_vlan_cfg.state,
vlan);
@@ -8455,21 +8458,12 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
vlan_info.qos = qos;
vlan_info.vlan_proto = ntohs(proto);
- /* update port based VLAN for PF */
- if (!vfid) {
- hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
- ret = hclge_update_port_base_vlan_cfg(vport, state, &vlan_info);
- hclge_notify_client(hdev, HNAE3_UP_CLIENT);
-
- return ret;
- }
-
if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) {
return hclge_update_port_base_vlan_cfg(vport, state,
&vlan_info);
} else {
ret = hclge_push_vf_port_base_vlan_info(&hdev->vport[0],
- (u8)vfid, state,
+ vport->vport_id, state,
vlan, qos,
ntohs(proto));
return ret;
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index 9170572346b5..a46f4189fde3 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -62,7 +62,7 @@ config TI_CPSW
config TI_CPSW_SWITCHDEV
tristate "TI CPSW Switch Support with switchdev"
depends on ARCH_DAVINCI || ARCH_OMAP2PLUS || COMPILE_TEST
- select NET_SWITCHDEV
+ depends on NET_SWITCHDEV
select TI_DAVINCI_MDIO
select MFD_SYSCON
select REGMAP
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 0cb1c2d0a8bc..3bf8a8b42983 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -564,8 +564,9 @@ static struct bpf_prog *get_filter(struct sock_fprog *uprog)
return NULL;
/* uprog->len is unsigned short, so no overflow here */
- fprog.len = uprog->len * sizeof(struct sock_filter);
- fprog.filter = memdup_user(uprog->filter, fprog.len);
+ fprog.len = uprog->len;
+ fprog.filter = memdup_user(uprog->filter,
+ uprog->len * sizeof(struct sock_filter));
if (IS_ERR(fprog.filter))
return ERR_CAST(fprog.filter);
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 293dd99b7fef..871d44746f5c 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -480,6 +480,7 @@ struct qeth_card_stats {
u64 rx_dropped_nomem;
u64 rx_dropped_notsupp;
+ u64 rx_dropped_runt;
/* rtnl_link_stats64 */
u64 rx_packets;
@@ -627,6 +628,7 @@ struct qeth_ipato {
struct qeth_channel {
struct ccw_device *ccwdev;
+ struct qeth_cmd_buffer *active_cmd;
enum qeth_channel_states state;
atomic_t irq_pending;
};
@@ -1037,6 +1039,8 @@ int qeth_do_run_thread(struct qeth_card *, unsigned long);
void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long);
void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long);
int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok);
+int qeth_stop_channel(struct qeth_channel *channel);
+
void qeth_print_status_message(struct qeth_card *);
int qeth_init_qdio_queues(struct qeth_card *);
int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *,
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index efcbe60220d1..b9a2349e4b90 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -515,7 +515,9 @@ static int __qeth_issue_next_read(struct qeth_card *card)
QETH_CARD_TEXT(card, 6, "noirqpnd");
rc = ccw_device_start(channel->ccwdev, ccw, (addr_t) iob, 0, 0);
- if (rc) {
+ if (!rc) {
+ channel->active_cmd = iob;
+ } else {
QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n",
rc, CARD_DEVID(card));
atomic_set(&channel->irq_pending, 0);
@@ -986,8 +988,21 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
QETH_CARD_TEXT(card, 5, "data");
}
- if (qeth_intparm_is_iob(intparm))
- iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
+ if (intparm == 0) {
+ QETH_CARD_TEXT(card, 5, "irqunsol");
+ } else if ((addr_t)intparm != (addr_t)channel->active_cmd) {
+ QETH_CARD_TEXT(card, 5, "irqunexp");
+
+ dev_err(&cdev->dev,
+ "Received IRQ with intparm %lx, expected %px\n",
+ intparm, channel->active_cmd);
+ if (channel->active_cmd)
+ qeth_cancel_cmd(channel->active_cmd, -EIO);
+ } else {
+ iob = (struct qeth_cmd_buffer *) (addr_t)intparm;
+ }
+
+ channel->active_cmd = NULL;
rc = qeth_check_irb_error(card, cdev, irb);
if (rc) {
@@ -1007,15 +1022,10 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC))
channel->state = CH_STATE_HALTED;
- if (intparm == QETH_CLEAR_CHANNEL_PARM) {
- QETH_CARD_TEXT(card, 6, "clrchpar");
- /* we don't have to handle this further */
- intparm = 0;
- }
- if (intparm == QETH_HALT_CHANNEL_PARM) {
- QETH_CARD_TEXT(card, 6, "hltchpar");
- /* we don't have to handle this further */
- intparm = 0;
+ if (iob && (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC |
+ SCSW_FCTL_HALT_FUNC))) {
+ qeth_cancel_cmd(iob, -ECANCELED);
+ iob = NULL;
}
cstat = irb->scsw.cmd.cstat;
@@ -1408,7 +1418,7 @@ static int qeth_clear_channel(struct qeth_card *card,
QETH_CARD_TEXT(card, 3, "clearch");
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
- rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
+ rc = ccw_device_clear(channel->ccwdev, (addr_t)channel->active_cmd);
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (rc)
@@ -1430,7 +1440,7 @@ static int qeth_halt_channel(struct qeth_card *card,
QETH_CARD_TEXT(card, 3, "haltch");
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
- rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
+ rc = ccw_device_halt(channel->ccwdev, (addr_t)channel->active_cmd);
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (rc)
@@ -1444,6 +1454,25 @@ static int qeth_halt_channel(struct qeth_card *card,
return 0;
}
+int qeth_stop_channel(struct qeth_channel *channel)
+{
+ struct ccw_device *cdev = channel->ccwdev;
+ int rc;
+
+ rc = ccw_device_set_offline(cdev);
+
+ spin_lock_irq(get_ccwdev_lock(cdev));
+ if (channel->active_cmd) {
+ dev_err(&cdev->dev, "Stopped channel while cmd %px was still active\n",
+ channel->active_cmd);
+ channel->active_cmd = NULL;
+ }
+ spin_unlock_irq(get_ccwdev_lock(cdev));
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_stop_channel);
+
static int qeth_halt_channels(struct qeth_card *card)
{
int rc1 = 0, rc2 = 0, rc3 = 0;
@@ -1746,6 +1775,8 @@ static int qeth_send_control_data(struct qeth_card *card,
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
rc = ccw_device_start_timeout(channel->ccwdev, __ccw_from_cmd(iob),
(addr_t) iob, 0, 0, timeout);
+ if (!rc)
+ channel->active_cmd = iob;
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (rc) {
QETH_DBF_MESSAGE(2, "qeth_send_control_data on device %x: ccw_device_start rc = %i\n",
@@ -4667,12 +4698,12 @@ EXPORT_SYMBOL_GPL(qeth_vm_request_mac);
static void qeth_determine_capabilities(struct qeth_card *card)
{
+ struct qeth_channel *channel = &card->data;
+ struct ccw_device *ddev = channel->ccwdev;
int rc;
- struct ccw_device *ddev;
int ddev_offline = 0;
QETH_CARD_TEXT(card, 2, "detcapab");
- ddev = CARD_DDEV(card);
if (!ddev->online) {
ddev_offline = 1;
rc = ccw_device_set_online(ddev);
@@ -4711,7 +4742,7 @@ static void qeth_determine_capabilities(struct qeth_card *card)
out_offline:
if (ddev_offline == 1)
- ccw_device_set_offline(ddev);
+ qeth_stop_channel(channel);
out:
return;
}
@@ -4911,9 +4942,9 @@ retry:
QETH_DBF_MESSAGE(2, "Retrying to do IDX activates on device %x.\n",
CARD_DEVID(card));
rc = qeth_qdio_clear_card(card, !IS_IQD(card));
- ccw_device_set_offline(CARD_DDEV(card));
- ccw_device_set_offline(CARD_WDEV(card));
- ccw_device_set_offline(CARD_RDEV(card));
+ qeth_stop_channel(&card->data);
+ qeth_stop_channel(&card->write);
+ qeth_stop_channel(&card->read);
qdio_free(CARD_DDEV(card));
rc = ccw_device_set_online(CARD_RDEV(card));
if (rc)
@@ -5028,27 +5059,15 @@ out:
}
EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card);
-static void qeth_create_skb_frag(struct qdio_buffer_element *element,
- struct sk_buff *skb, int offset, int data_len)
+static void qeth_create_skb_frag(struct sk_buff *skb, char *data, int data_len)
{
- struct page *page = virt_to_page(element->addr);
+ struct page *page = virt_to_page(data);
unsigned int next_frag;
- /* first fill the linear space */
- if (!skb->len) {
- unsigned int linear = min(data_len, skb_tailroom(skb));
-
- skb_put_data(skb, element->addr + offset, linear);
- data_len -= linear;
- if (!data_len)
- return;
- offset += linear;
- /* fall through to add page frag for remaining data */
- }
-
next_frag = skb_shinfo(skb)->nr_frags;
get_page(page);
- skb_add_rx_frag(skb, next_frag, page, offset, data_len, data_len);
+ skb_add_rx_frag(skb, next_frag, page, offset_in_page(data), data_len,
+ data_len);
}
static inline int qeth_is_last_sbale(struct qdio_buffer_element *sbale)
@@ -5063,13 +5082,12 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
{
struct qdio_buffer_element *element = *__element;
struct qdio_buffer *buffer = qethbuffer->buffer;
+ unsigned int linear_len = 0;
int offset = *__offset;
bool use_rx_sg = false;
unsigned int headroom;
struct sk_buff *skb;
int skb_len = 0;
- void *data_ptr;
- int data_len;
next_packet:
/* qeth_hdr must not cross element boundaries */
@@ -5082,29 +5100,41 @@ next_packet:
*hdr = element->addr + offset;
offset += sizeof(struct qeth_hdr);
+ skb = NULL;
+
switch ((*hdr)->hdr.l2.id) {
case QETH_HEADER_TYPE_LAYER2:
skb_len = (*hdr)->hdr.l2.pkt_length;
+ linear_len = ETH_HLEN;
headroom = 0;
break;
case QETH_HEADER_TYPE_LAYER3:
skb_len = (*hdr)->hdr.l3.length;
if (!IS_LAYER3(card)) {
QETH_CARD_STAT_INC(card, rx_dropped_notsupp);
- skb = NULL;
goto walk_packet;
}
+ if ((*hdr)->hdr.l3.flags & QETH_HDR_PASSTHRU) {
+ linear_len = ETH_HLEN;
+ headroom = 0;
+ break;
+ }
+
+ if ((*hdr)->hdr.l3.flags & QETH_HDR_IPV6)
+ linear_len = sizeof(struct ipv6hdr);
+ else
+ linear_len = sizeof(struct iphdr);
headroom = ETH_HLEN;
break;
case QETH_HEADER_TYPE_OSN:
skb_len = (*hdr)->hdr.osn.pdu_length;
if (!IS_OSN(card)) {
QETH_CARD_STAT_INC(card, rx_dropped_notsupp);
- skb = NULL;
goto walk_packet;
}
+ linear_len = skb_len;
headroom = sizeof(struct qeth_hdr);
break;
default:
@@ -5117,8 +5147,10 @@ next_packet:
return NULL;
}
- if (!skb_len)
- return NULL;
+ if (skb_len < linear_len) {
+ QETH_CARD_STAT_INC(card, rx_dropped_runt);
+ goto walk_packet;
+ }
use_rx_sg = (card->options.cq == QETH_CQ_ENABLED) ||
((skb_len >= card->options.rx_sg_cb) &&
@@ -5130,9 +5162,9 @@ next_packet:
skb = qethbuffer->rx_skb;
qethbuffer->rx_skb = NULL;
} else {
- unsigned int linear = (use_rx_sg) ? QETH_RX_PULL_LEN : skb_len;
-
- skb = napi_alloc_skb(&card->napi, linear + headroom);
+ if (!use_rx_sg)
+ linear_len = skb_len;
+ skb = napi_alloc_skb(&card->napi, linear_len + headroom);
}
if (!skb)
@@ -5141,18 +5173,32 @@ next_packet:
skb_reserve(skb, headroom);
walk_packet:
- data_ptr = element->addr + offset;
while (skb_len) {
- data_len = min(skb_len, (int)(element->length - offset));
+ int data_len = min(skb_len, (int)(element->length - offset));
+ char *data = element->addr + offset;
+
+ skb_len -= data_len;
+ offset += data_len;
+ /* Extract data from current element: */
if (skb && data_len) {
- if (use_rx_sg)
- qeth_create_skb_frag(element, skb, offset,
- data_len);
- else
- skb_put_data(skb, data_ptr, data_len);
+ if (linear_len) {
+ unsigned int copy_len;
+
+ copy_len = min_t(unsigned int, linear_len,
+ data_len);
+
+ skb_put_data(skb, data, copy_len);
+ linear_len -= copy_len;
+ data_len -= copy_len;
+ data += copy_len;
+ }
+
+ if (data_len)
+ qeth_create_skb_frag(skb, data, data_len);
}
- skb_len -= data_len;
+
+ /* Step forward to next element: */
if (skb_len) {
if (qeth_is_last_sbale(element)) {
QETH_CARD_TEXT(card, 4, "unexeob");
@@ -5166,9 +5212,6 @@ walk_packet:
}
element++;
offset = 0;
- data_ptr = element->addr;
- } else {
- offset += data_len;
}
}
@@ -6268,7 +6311,8 @@ void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
card->stats.rx_frame_errors +
card->stats.rx_fifo_errors;
stats->rx_dropped = card->stats.rx_dropped_nomem +
- card->stats.rx_dropped_notsupp;
+ card->stats.rx_dropped_notsupp +
+ card->stats.rx_dropped_runt;
stats->multicast = card->stats.rx_multicast;
stats->rx_length_errors = card->stats.rx_length_errors;
stats->rx_frame_errors = card->stats.rx_frame_errors;
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
index 53fcf6641154..88f4dc140751 100644
--- a/drivers/s390/net/qeth_core_mpc.h
+++ b/drivers/s390/net/qeth_core_mpc.h
@@ -29,20 +29,6 @@ extern unsigned char IPA_PDU_HEADER[];
#define QETH_TIMEOUT (10 * HZ)
#define QETH_IPA_TIMEOUT (45 * HZ)
-#define QETH_CLEAR_CHANNEL_PARM -10
-#define QETH_HALT_CHANNEL_PARM -11
-
-static inline bool qeth_intparm_is_iob(unsigned long intparm)
-{
- switch (intparm) {
- case QETH_CLEAR_CHANNEL_PARM:
- case QETH_HALT_CHANNEL_PARM:
- case 0:
- return false;
- }
- return true;
-}
-
/*****************************************************************************/
/* IP Assist related definitions */
/*****************************************************************************/
diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c
index f7485c6dea25..ab59bc975719 100644
--- a/drivers/s390/net/qeth_ethtool.c
+++ b/drivers/s390/net/qeth_ethtool.c
@@ -51,6 +51,7 @@ static const struct qeth_stats card_stats[] = {
QETH_CARD_STAT("rx0 SG page allocs", rx_sg_alloc_page),
QETH_CARD_STAT("rx0 dropped, no memory", rx_dropped_nomem),
QETH_CARD_STAT("rx0 dropped, bad format", rx_dropped_notsupp),
+ QETH_CARD_STAT("rx0 dropped, runt", rx_dropped_runt),
};
#define TXQ_STATS_LEN ARRAY_SIZE(txq_stats)
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 989935d67b31..9086bc04fa6b 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -845,9 +845,9 @@ static int qeth_l2_set_online(struct ccwgroup_device *gdev)
out_remove:
qeth_l2_stop_card(card);
- ccw_device_set_offline(CARD_DDEV(card));
- ccw_device_set_offline(CARD_WDEV(card));
- ccw_device_set_offline(CARD_RDEV(card));
+ qeth_stop_channel(&card->data);
+ qeth_stop_channel(&card->write);
+ qeth_stop_channel(&card->read);
qdio_free(CARD_DDEV(card));
mutex_unlock(&card->conf_mutex);
@@ -878,9 +878,9 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
rtnl_unlock();
qeth_l2_stop_card(card);
- rc = ccw_device_set_offline(CARD_DDEV(card));
- rc2 = ccw_device_set_offline(CARD_WDEV(card));
- rc3 = ccw_device_set_offline(CARD_RDEV(card));
+ rc = qeth_stop_channel(&card->data);
+ rc2 = qeth_stop_channel(&card->write);
+ rc3 = qeth_stop_channel(&card->read);
if (!rc)
rc = (rc2) ? rc2 : rc3;
if (rc)
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index e7ce73b9f016..27126330a4b0 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2259,9 +2259,9 @@ static int qeth_l3_set_online(struct ccwgroup_device *gdev)
return 0;
out_remove:
qeth_l3_stop_card(card);
- ccw_device_set_offline(CARD_DDEV(card));
- ccw_device_set_offline(CARD_WDEV(card));
- ccw_device_set_offline(CARD_RDEV(card));
+ qeth_stop_channel(&card->data);
+ qeth_stop_channel(&card->write);
+ qeth_stop_channel(&card->read);
qdio_free(CARD_DDEV(card));
mutex_unlock(&card->conf_mutex);
@@ -2297,9 +2297,10 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
call_netdevice_notifiers(NETDEV_REBOOT, card->dev);
rtnl_unlock();
}
- rc = ccw_device_set_offline(CARD_DDEV(card));
- rc2 = ccw_device_set_offline(CARD_WDEV(card));
- rc3 = ccw_device_set_offline(CARD_RDEV(card));
+
+ rc = qeth_stop_channel(&card->data);
+ rc2 = qeth_stop_channel(&card->write);
+ rc3 = qeth_stop_channel(&card->read);
if (!rc)
rc = (rc2) ? rc2 : rc3;
if (rc)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 5aea72fe8498..e9133bcf0544 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3529,7 +3529,7 @@ int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci);
int skb_vlan_pop(struct sk_buff *skb);
int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto,
- int mac_len);
+ int mac_len, bool ethernet);
int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len,
bool ethernet);
int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 312e80e86898..973a71f4bc89 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -5484,7 +5484,7 @@ static void skb_mod_eth_type(struct sk_buff *skb, struct ethhdr *hdr,
* Returns 0 on success, -errno otherwise.
*/
int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto,
- int mac_len)
+ int mac_len, bool ethernet)
{
struct mpls_shim_hdr *lse;
int err;
@@ -5515,7 +5515,7 @@ int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto,
lse->label_stack_entry = mpls_lse;
skb_postpush_rcsum(skb, lse, MPLS_HLEN);
- if (skb->dev && skb->dev->type == ARPHRD_ETHER)
+ if (ethernet)
skb_mod_eth_type(skb, eth_hdr(skb), mpls_proto);
skb->protocol = mpls_proto;
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index f509b495451a..b01e1bae4ddc 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -227,8 +227,13 @@ static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
struct hsr_port *master;
master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
- skb->dev = master->dev;
- hsr_forward_skb(skb, master);
+ if (master) {
+ skb->dev = master->dev;
+ hsr_forward_skb(skb, master);
+ } else {
+ atomic_long_inc(&dev->tx_dropped);
+ dev_kfree_skb_any(skb);
+ }
return NETDEV_TX_OK;
}
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 91e210061bb3..4c8395462303 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -166,7 +166,8 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
int err;
err = skb_mpls_push(skb, mpls->mpls_lse, mpls->mpls_ethertype,
- skb->mac_len);
+ skb->mac_len,
+ ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET);
if (err)
return err;
diff --git a/net/sched/act_mpls.c b/net/sched/act_mpls.c
index a7d856203af1..be3f215cd027 100644
--- a/net/sched/act_mpls.c
+++ b/net/sched/act_mpls.c
@@ -83,7 +83,8 @@ static int tcf_mpls_act(struct sk_buff *skb, const struct tc_action *a,
break;
case TCA_MPLS_ACT_PUSH:
new_lse = tcf_mpls_get_lse(NULL, p, !eth_p_mpls(skb->protocol));
- if (skb_mpls_push(skb, new_lse, p->tcfm_proto, mac_len))
+ if (skb_mpls_push(skb, new_lse, p->tcfm_proto, mac_len,
+ skb->dev && skb->dev->type == ARPHRD_ETHER))
goto drop;
break;
case TCA_MPLS_ACT_MODIFY: