.. | .. |
---|
186 | 186 | set_prp_LSDU_size(trailer, lsdu_size); |
---|
187 | 187 | trailer->sequence_nr = htons(frame->sequence_nr); |
---|
188 | 188 | trailer->PRP_suffix = htons(ETH_P_PRP); |
---|
| 189 | + skb->protocol = eth_hdr(skb)->h_proto; |
---|
189 | 190 | |
---|
190 | 191 | return skb; |
---|
191 | 192 | } |
---|
.. | .. |
---|
226 | 227 | hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto; |
---|
227 | 228 | hsr_ethhdr->ethhdr.h_proto = htons(proto_version ? |
---|
228 | 229 | ETH_P_HSR : ETH_P_PRP); |
---|
| 230 | + skb->protocol = hsr_ethhdr->ethhdr.h_proto; |
---|
229 | 231 | |
---|
230 | 232 | return skb; |
---|
231 | 233 | } |
---|
.. | .. |
---|
435 | 437 | { |
---|
436 | 438 | struct hsr_port *port = frame->port_rcv; |
---|
437 | 439 | struct hsr_priv *hsr = port->hsr; |
---|
438 | | - unsigned long irqflags; |
---|
439 | 440 | |
---|
440 | 441 | frame->skb_hsr = NULL; |
---|
441 | 442 | frame->skb_prp = NULL; |
---|
.. | .. |
---|
445 | 446 | frame->is_from_san = true; |
---|
446 | 447 | } else { |
---|
447 | 448 | /* Sequence nr for the master node */ |
---|
448 | | - spin_lock_irqsave(&hsr->seqnr_lock, irqflags); |
---|
| 449 | + lockdep_assert_held(&hsr->seqnr_lock); |
---|
449 | 450 | frame->sequence_nr = hsr->sequence_nr; |
---|
450 | 451 | hsr->sequence_nr++; |
---|
451 | | - spin_unlock_irqrestore(&hsr->seqnr_lock, irqflags); |
---|
452 | 452 | } |
---|
453 | 453 | } |
---|
454 | 454 | |
---|
455 | 455 | int hsr_fill_frame_info(__be16 proto, struct sk_buff *skb, |
---|
456 | 456 | struct hsr_frame_info *frame) |
---|
457 | 457 | { |
---|
458 | | - if (proto == htons(ETH_P_PRP) || |
---|
| 458 | + struct hsr_port *port = frame->port_rcv; |
---|
| 459 | + struct hsr_priv *hsr = port->hsr; |
---|
| 460 | + |
---|
| 461 | + /* HSRv0 supervisory frames double as a tag so treat them as tagged. */ |
---|
| 462 | + if ((!hsr->prot_version && proto == htons(ETH_P_PRP)) || |
---|
459 | 463 | proto == htons(ETH_P_HSR)) { |
---|
460 | 464 | /* Check if skb contains hsr_ethhdr */ |
---|
461 | 465 | if (skb->mac_len < sizeof(struct hsr_ethhdr)) |
---|
.. | .. |
---|
527 | 531 | proto = vlan_hdr->vlanhdr.h_vlan_encapsulated_proto; |
---|
528 | 532 | /* FIXME: */ |
---|
529 | 533 | netdev_warn_once(skb->dev, "VLAN not yet supported"); |
---|
| 534 | + return -EINVAL; |
---|
530 | 535 | } |
---|
531 | 536 | |
---|
532 | 537 | frame->is_from_san = false; |
---|
.. | .. |
---|
545 | 550 | { |
---|
546 | 551 | struct hsr_frame_info frame; |
---|
547 | 552 | |
---|
| 553 | + rcu_read_lock(); |
---|
548 | 554 | if (fill_frame_info(&frame, skb, port) < 0) |
---|
549 | 555 | goto out_drop; |
---|
550 | 556 | |
---|
551 | 557 | hsr_register_frame_in(frame.node_src, port, frame.sequence_nr); |
---|
552 | 558 | hsr_forward_do(&frame); |
---|
| 559 | + rcu_read_unlock(); |
---|
553 | 560 | /* Gets called for ingress frames as well as egress from master port. |
---|
554 | 561 | * So check and increment stats for master port only here. |
---|
555 | 562 | */ |
---|
.. | .. |
---|
564 | 571 | return; |
---|
565 | 572 | |
---|
566 | 573 | out_drop: |
---|
| 574 | + rcu_read_unlock(); |
---|
567 | 575 | port->dev->stats.tx_dropped++; |
---|
568 | 576 | kfree_skb(skb); |
---|
569 | 577 | } |
---|