| .. | .. |
|---|
| 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 | } |
|---|