summaryrefslogtreecommitdiff
path: root/net/hsr/hsr_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/hsr/hsr_device.c')
-rw-r--r--net/hsr/hsr_device.c55
1 files changed, 22 insertions, 33 deletions
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index fdd9c00082a8..60839272ab74 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -376,8 +376,10 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
skb->dev = master->dev;
skb_reset_mac_header(skb);
skb_reset_mac_len(skb);
+ spin_lock_bh(&hsr->seqnr_lock);
hsr_forward_skb(skb, master);
INC_CNT_RX_C(hsr);
+ spin_unlock_bh(&hsr->seqnr_lock);
} else {
atomic_long_inc(&dev->tx_dropped);
dev_kfree_skb_any(skb);
@@ -390,11 +392,12 @@ static const struct header_ops hsr_header_ops = {
.parse = eth_header_parse,
};
-static struct sk_buff *hsr_init_skb(struct hsr_port *master, u16 proto)
+static struct sk_buff *hsr_init_skb(struct hsr_port *master)
{
struct hsr_priv *hsr = master->hsr;
struct sk_buff *skb;
int hlen, tlen;
+ u16 proto;
int len;
hsr = master->hsr;
@@ -421,6 +424,8 @@ static struct sk_buff *hsr_init_skb(struct hsr_port *master, u16 proto)
skb_reserve(skb, hlen);
skb->dev = master->dev;
+ proto = ETH_P_PRP;
+
if (hsr->use_vlan_for_sv) {
proto = ETH_P_8021Q;
skb->priority = hsr->sv_frame_pcp;
@@ -454,9 +459,7 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
struct hsr_tag *hsr_tag = NULL;
struct hsr_sup_payload *hsr_sp;
struct hsr_sup_tag *hsr_stag;
- unsigned long irqflags;
struct sk_buff *skb;
- u16 proto;
struct vlan_hdr *vhdr;
u16 vlan_tci = 0;
@@ -467,12 +470,7 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
hsr->announce_count++;
}
- if (!hsr->prot_version)
- proto = ETH_P_PRP;
- else
- proto = ETH_P_HSR;
-
- skb = hsr_init_skb(master, proto);
+ skb = hsr_init_skb(master);
if (!skb) {
WARN_ONCE(1, "HSR: Could not send supervision frame\n");
return;
@@ -485,7 +483,7 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
if (hsr->sv_frame_dei)
vlan_tci |= VLAN_CFI_MASK;
vhdr->h_vlan_TCI = htons(vlan_tci);
- vhdr->h_vlan_encapsulated_proto = htons(proto);
+ vhdr->h_vlan_encapsulated_proto = htons(ETH_P_PRP);
}
if (hsr->prot_version > 0) {
@@ -499,17 +497,14 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version);
/* From HSRv1 on we have separate supervision sequence numbers. */
- spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags);
+ spin_lock_bh(&hsr->seqnr_lock);
if (hsr->prot_version > 0) {
hsr_stag->sequence_nr = htons(hsr->sup_sequence_nr);
hsr->sup_sequence_nr++;
- hsr_tag->sequence_nr = htons(hsr->sequence_nr);
- hsr->sequence_nr++;
} else {
hsr_stag->sequence_nr = htons(hsr->sequence_nr);
hsr->sequence_nr++;
}
- spin_unlock_irqrestore(&hsr->seqnr_lock, irqflags);
hsr_stag->HSR_TLV_type = type;
/* TODO: Why 12 in HSRv0? */
@@ -521,16 +516,20 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr);
if (!hsr->use_vlan_for_sv) {
- if (skb_put_padto(skb, ETH_ZLEN + HSR_HLEN))
+ if (skb_put_padto(skb, ETH_ZLEN)) {
+ spin_unlock_bh(&hsr->seqnr_lock);
return;
+ }
} else {
- if (skb_put_padto(skb, ETH_ZLEN + HSR_HLEN + VLAN_HLEN))
+ if (skb_put_padto(skb, ETH_ZLEN + VLAN_HLEN)) {
+ spin_unlock_bh(&hsr->seqnr_lock);
return;
+ }
}
hsr_forward_skb(skb, master);
INC_CNT_TX_SUP(hsr);
-
+ spin_unlock_bh(&hsr->seqnr_lock);
return;
}
@@ -540,12 +539,9 @@ static void send_prp_supervision_frame(struct hsr_port *master,
struct hsr_priv *hsr = master->hsr;
struct hsr_sup_payload *hsr_sp;
struct hsr_sup_tag *hsr_stag;
- unsigned long irqflags;
struct sk_buff *skb;
- struct prp_rct *rct;
- u8 *tail;
- skb = hsr_init_skb(master, ETH_P_PRP);
+ skb = hsr_init_skb(master);
if (!skb) {
WARN_ONCE(1, "PRP: Could not send supervision frame\n");
return;
@@ -557,7 +553,7 @@ static void send_prp_supervision_frame(struct hsr_port *master,
set_hsr_stag_HSR_ver(hsr_stag, (hsr->prot_version ? 1 : 0));
/* From HSRv1 on we have separate supervision sequence numbers. */
- spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags);
+ spin_lock_bh(&hsr->seqnr_lock);
hsr_stag->sequence_nr = htons(hsr->sup_sequence_nr);
hsr->sup_sequence_nr++;
hsr_stag->HSR_TLV_type = PRP_TLV_LIFE_CHECK_DD;
@@ -567,21 +563,14 @@ static void send_prp_supervision_frame(struct hsr_port *master,
hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload));
ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr);
- if (skb_put_padto(skb, ETH_ZLEN + HSR_HLEN)) {
- spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags);
+ if (skb_put_padto(skb, ETH_ZLEN)) {
+ spin_unlock_bh(&hsr->seqnr_lock);
return;
}
- tail = skb_tail_pointer(skb) - HSR_HLEN;
- rct = (struct prp_rct *)tail;
- rct->PRP_suffix = htons(ETH_P_PRP);
- set_prp_LSDU_size(rct, HSR_V1_SUP_LSDUSIZE);
- rct->sequence_nr = htons(hsr->sequence_nr);
- hsr->sequence_nr++;
- spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags);
-
hsr_forward_skb(skb, master);
INC_CNT_TX_SUP(hsr);
+ spin_unlock_bh(&hsr->seqnr_lock);
}
/* Announce (supervision frame) timer function
@@ -828,7 +817,7 @@ void hsr_dev_setup(struct net_device *dev)
dev->netdev_ops = &hsr_device_ops;
dev->ethtool_ops = &hsr_ethtool_ops;
SET_NETDEV_DEVTYPE(dev, &hsr_type);
- dev->priv_flags |= IFF_NO_QUEUE;
+ dev->priv_flags |= IFF_NO_QUEUE | IFF_DISABLE_NETPOLL;
dev->needs_free_netdev = true;