Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 369874
b: refs/heads/master
c: dd981ab
h: refs/heads/master
v: v3
  • Loading branch information
Antonio Quartulli authored and Antonio Quartulli committed Apr 22, 2013
1 parent 4a2af24 commit 66e4b48
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 164 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 093162553c33e9479283e107b4431378271c735d
refs/heads/master: dd981ab091cde09bb9eb23c8d81305ba615ee30c
7 changes: 0 additions & 7 deletions trunk/drivers/net/ethernet/emulex/benet/be.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,6 @@ enum vf_state {
#define BE_FLAGS_WORKER_SCHEDULED (1 << 3)
#define BE_UC_PMAC_COUNT 30
#define BE_VF_UC_PMAC_COUNT 2
#define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11)

struct phy_info {
u8 transceiver;
Expand Down Expand Up @@ -435,7 +434,6 @@ struct be_adapter {
u8 wol_cap;
bool wol;
u32 uc_macs; /* Count of secondary UC MAC programmed */
u16 qnq_vid;
u32 msg_enable;
int be_get_temp_freq;
u16 max_mcast_mac;
Expand Down Expand Up @@ -650,11 +648,6 @@ static inline bool be_is_wol_excluded(struct be_adapter *adapter)
}
}

static inline int qnq_async_evt_rcvd(struct be_adapter *adapter)
{
return adapter->flags & BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
}

extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
u16 num_popped);
extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
Expand Down
32 changes: 0 additions & 32 deletions trunk/drivers/net/ethernet/emulex/benet/be_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,27 +263,6 @@ static void be_async_grp5_evt_process(struct be_adapter *adapter,
}
}

static void be_async_dbg_evt_process(struct be_adapter *adapter,
u32 trailer, struct be_mcc_compl *cmp)
{
u8 event_type = 0;
struct be_async_event_qnq *evt = (struct be_async_event_qnq *) cmp;

event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) &
ASYNC_TRAILER_EVENT_TYPE_MASK;

switch (event_type) {
case ASYNC_DEBUG_EVENT_TYPE_QNQ:
if (evt->valid)
adapter->qnq_vid = le16_to_cpu(evt->vlan_tag);
adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
break;
default:
dev_warn(&adapter->pdev->dev, "Unknown debug event\n");
break;
}
}

static inline bool is_link_state_evt(u32 trailer)
{
return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
Expand All @@ -298,13 +277,6 @@ static inline bool is_grp5_evt(u32 trailer)
ASYNC_EVENT_CODE_GRP_5);
}

static inline bool is_dbg_evt(u32 trailer)
{
return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
ASYNC_TRAILER_EVENT_CODE_MASK) ==
ASYNC_EVENT_CODE_QNQ);
}

static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
{
struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq;
Expand Down Expand Up @@ -353,9 +325,6 @@ int be_process_mcc(struct be_adapter *adapter)
else if (is_grp5_evt(compl->flags))
be_async_grp5_evt_process(adapter,
compl->flags, compl);
else if (is_dbg_evt(compl->flags))
be_async_dbg_evt_process(adapter,
compl->flags, compl);
} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
status = be_mcc_compl_process(adapter, compl);
atomic_dec(&mcc_obj->q.used);
Expand Down Expand Up @@ -1053,7 +1022,6 @@ int be_cmd_mccq_ext_create(struct be_adapter *adapter,

/* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */
req->async_event_bitmap[0] = cpu_to_le32(0x00000022);
req->async_event_bitmap[0] |= cpu_to_le32(1 << ASYNC_EVENT_CODE_QNQ);
be_dws_cpu_to_le(ctxt, sizeof(req->context));

be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
Expand Down
13 changes: 0 additions & 13 deletions trunk/drivers/net/ethernet/emulex/benet/be_cmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@ struct be_mcc_compl {
#define ASYNC_EVENT_QOS_SPEED 0x1
#define ASYNC_EVENT_COS_PRIORITY 0x2
#define ASYNC_EVENT_PVID_STATE 0x3
#define ASYNC_EVENT_CODE_QNQ 0x6
#define ASYNC_DEBUG_EVENT_TYPE_QNQ 1

struct be_async_event_trailer {
u32 code;
};
Expand Down Expand Up @@ -147,16 +144,6 @@ struct be_async_event_grp5_pvid_state {
struct be_async_event_trailer trailer;
} __packed;

/* async event indicating outer VLAN tag in QnQ */
struct be_async_event_qnq {
u8 valid; /* Indicates if outer VLAN is valid */
u8 rsvd0;
u16 vlan_tag;
u32 event_tag;
u8 rsvd1[4];
struct be_async_event_trailer trailer;
} __packed;

struct be_mcc_mailbox {
struct be_mcc_wrb wrb;
struct be_mcc_compl compl;
Expand Down
121 changes: 17 additions & 104 deletions trunk/drivers/net/ethernet/emulex/benet/be_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,8 +626,13 @@ static inline u16 be_get_tx_vlan_tag(struct be_adapter *adapter,
return vlan_tag;
}

static int be_vlan_tag_chk(struct be_adapter *adapter, struct sk_buff *skb)
{
return vlan_tx_tag_present(skb) || adapter->pvid;
}

static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
struct sk_buff *skb, u32 wrb_cnt, u32 len, bool skip_hw_vlan)
struct sk_buff *skb, u32 wrb_cnt, u32 len)
{
u16 vlan_tag;

Expand All @@ -654,9 +659,8 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, hdr, vlan_tag);
}

/* To skip HW VLAN tagging: evt = 1, compl = 0 */
AMAP_SET_BITS(struct amap_eth_hdr_wrb, complete, hdr, !skip_hw_vlan);
AMAP_SET_BITS(struct amap_eth_hdr_wrb, event, hdr, 1);
AMAP_SET_BITS(struct amap_eth_hdr_wrb, complete, hdr, 1);
AMAP_SET_BITS(struct amap_eth_hdr_wrb, num_wrb, hdr, wrb_cnt);
AMAP_SET_BITS(struct amap_eth_hdr_wrb, len, hdr, len);
}
Expand All @@ -679,8 +683,7 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
}

static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq,
struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb,
bool skip_hw_vlan)
struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb)
{
dma_addr_t busaddr;
int i, copied = 0;
Expand Down Expand Up @@ -729,7 +732,7 @@ static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq,
queue_head_inc(txq);
}

wrb_fill_hdr(adapter, hdr, first_skb, wrb_cnt, copied, skip_hw_vlan);
wrb_fill_hdr(adapter, hdr, first_skb, wrb_cnt, copied);
be_dws_cpu_to_le(hdr, sizeof(*hdr));

return copied;
Expand All @@ -746,8 +749,7 @@ static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq,
}

static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
struct sk_buff *skb,
bool *skip_hw_vlan)
struct sk_buff *skb)
{
u16 vlan_tag = 0;

Expand All @@ -762,67 +764,9 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
skb->vlan_tci = 0;
}

if (qnq_async_evt_rcvd(adapter) && adapter->pvid) {
if (!vlan_tag)
vlan_tag = adapter->pvid;
if (skip_hw_vlan)
*skip_hw_vlan = true;
}

if (vlan_tag) {
skb = __vlan_put_tag(skb, vlan_tag);
if (unlikely(!skb))
return skb;

skb->vlan_tci = 0;
}

/* Insert the outer VLAN, if any */
if (adapter->qnq_vid) {
vlan_tag = adapter->qnq_vid;
skb = __vlan_put_tag(skb, vlan_tag);
if (unlikely(!skb))
return skb;
if (skip_hw_vlan)
*skip_hw_vlan = true;
}

return skb;
}

static bool be_ipv6_exthdr_check(struct sk_buff *skb)
{
struct ethhdr *eh = (struct ethhdr *)skb->data;
u16 offset = ETH_HLEN;

if (eh->h_proto == htons(ETH_P_IPV6)) {
struct ipv6hdr *ip6h = (struct ipv6hdr *)(skb->data + offset);

offset += sizeof(struct ipv6hdr);
if (ip6h->nexthdr != NEXTHDR_TCP &&
ip6h->nexthdr != NEXTHDR_UDP) {
struct ipv6_opt_hdr *ehdr =
(struct ipv6_opt_hdr *) (skb->data + offset);

/* offending pkt: 2nd byte following IPv6 hdr is 0xff */
if (ehdr->hdrlen == 0xff)
return true;
}
}
return false;
}

static int be_vlan_tag_tx_chk(struct be_adapter *adapter, struct sk_buff *skb)
{
return vlan_tx_tag_present(skb) || adapter->pvid || adapter->qnq_vid;
}

static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, struct sk_buff *skb)
{
return BE3_chip(adapter) &&
be_ipv6_exthdr_check(skb);
}

static netdev_tx_t be_xmit(struct sk_buff *skb,
struct net_device *netdev)
{
Expand All @@ -833,64 +777,33 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
u32 wrb_cnt = 0, copied = 0;
u32 start = txq->head, eth_hdr_len;
bool dummy_wrb, stopped = false;
bool skip_hw_vlan = false;
struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;

eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ?
VLAN_ETH_HLEN : ETH_HLEN;

/* For padded packets, BE HW modifies tot_len field in IP header
* incorrecly when VLAN tag is inserted by HW.
/* HW has a bug which considers padding bytes as legal
* and modifies the IPv4 hdr's 'tot_len' field
*/
if (skb->len <= 60 && vlan_tx_tag_present(skb) && is_ipv4_pkt(skb)) {
if (skb->len <= 60 && be_vlan_tag_chk(adapter, skb) &&
is_ipv4_pkt(skb)) {
ip = (struct iphdr *)ip_hdr(skb);
pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
}

/* If vlan tag is already inlined in the packet, skip HW VLAN
* tagging in UMC mode
*/
if ((adapter->function_mode & UMC_ENABLED) &&
veh->h_vlan_proto == htons(ETH_P_8021Q))
skip_hw_vlan = true;

/* HW has a bug wherein it will calculate CSUM for VLAN
* pkts even though it is disabled.
* Manually insert VLAN in pkt.
*/
if (skb->ip_summed != CHECKSUM_PARTIAL &&
vlan_tx_tag_present(skb)) {
skb = be_insert_vlan_in_pkt(adapter, skb, &skip_hw_vlan);
if (unlikely(!skb))
goto tx_drop;
}

/* HW may lockup when VLAN HW tagging is requested on
* certain ipv6 packets. Drop such pkts if the HW workaround to
* skip HW tagging is not enabled by FW.
*/
if (unlikely(be_ipv6_tx_stall_chk(adapter, skb) &&
(adapter->pvid || adapter->qnq_vid) &&
!qnq_async_evt_rcvd(adapter)))
goto tx_drop;

/* Manual VLAN tag insertion to prevent:
* ASIC lockup when the ASIC inserts VLAN tag into
* certain ipv6 packets. Insert VLAN tags in driver,
* and set event, completion, vlan bits accordingly
* in the Tx WRB.
*/
if (be_ipv6_tx_stall_chk(adapter, skb) &&
be_vlan_tag_tx_chk(adapter, skb)) {
skb = be_insert_vlan_in_pkt(adapter, skb, &skip_hw_vlan);
be_vlan_tag_chk(adapter, skb)) {
skb = be_insert_vlan_in_pkt(adapter, skb);
if (unlikely(!skb))
goto tx_drop;
}

wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb);

copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb,
skip_hw_vlan);
copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb);
if (copied) {
int gso_segs = skb_shinfo(skb)->gso_segs;

Expand Down
1 change: 0 additions & 1 deletion trunk/include/net/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,6 @@ static inline bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
skb_queue_len(&tp->ucopy.prequeue) == 0)
return false;

skb_dst_force(skb);
__skb_queue_tail(&tp->ucopy.prequeue, skb);
tp->ucopy.memory += skb->truesize;
if (tp->ucopy.memory > sk->sk_rcvbuf) {
Expand Down
11 changes: 5 additions & 6 deletions trunk/net/batman-adv/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -924,7 +924,7 @@ batadv_reroute_unicast_packet(struct batadv_priv *bat_priv,
}

static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
struct sk_buff *skb) {
struct sk_buff *skb, int hdr_len) {
uint8_t curr_ttvn, old_ttvn;
struct batadv_orig_node *orig_node;
struct ethhdr *ethhdr;
Expand All @@ -933,15 +933,15 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
int is_old_ttvn;

/* check if there is enough data before accessing it */
if (pskb_may_pull(skb, sizeof(*unicast_packet) + ETH_HLEN) < 0)
if (pskb_may_pull(skb, hdr_len + ETH_HLEN) < 0)
return 0;

/* create a copy of the skb (in case of for re-routing) to modify it. */
if (skb_cow(skb, sizeof(*unicast_packet)) < 0)
return 0;

unicast_packet = (struct batadv_unicast_packet *)skb->data;
ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet));
ethhdr = (struct ethhdr *)(skb->data + hdr_len);

/* check if the destination client was served by this node and it is now
* roaming. In this case, it means that the node has got a ROAM_ADV
Expand Down Expand Up @@ -1048,8 +1048,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,

if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
return NET_RX_DROP;

if (!batadv_check_unicast_ttvn(bat_priv, skb))
if (!batadv_check_unicast_ttvn(bat_priv, skb, hdr_size))
return NET_RX_DROP;

/* packet for me */
Expand Down Expand Up @@ -1093,7 +1092,7 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
return NET_RX_DROP;

if (!batadv_check_unicast_ttvn(bat_priv, skb))
if (!batadv_check_unicast_ttvn(bat_priv, skb, hdr_size))
return NET_RX_DROP;

unicast_packet = (struct batadv_unicast_frag_packet *)skb->data;
Expand Down

0 comments on commit 66e4b48

Please sign in to comment.