aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h29
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c196
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c7
3 files changed, 204 insertions, 28 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 9e8d1955dfcf..a4729c73ab80 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -612,9 +612,10 @@ struct bnx2x_fastpath {
612 * START_BD - describes packed 612 * START_BD - describes packed
613 * START_BD(splitted) - includes unpaged data segment for GSO 613 * START_BD(splitted) - includes unpaged data segment for GSO
614 * PARSING_BD - for TSO and CSUM data 614 * PARSING_BD - for TSO and CSUM data
615 * PARSING_BD2 - for encapsulation data
615 * Frag BDs - decribes pages for frags 616 * Frag BDs - decribes pages for frags
616 */ 617 */
617#define BDS_PER_TX_PKT 3 618#define BDS_PER_TX_PKT 4
618#define MAX_BDS_PER_TX_PKT (MAX_SKB_FRAGS + BDS_PER_TX_PKT) 619#define MAX_BDS_PER_TX_PKT (MAX_SKB_FRAGS + BDS_PER_TX_PKT)
619/* max BDs per tx packet including next pages */ 620/* max BDs per tx packet including next pages */
620#define MAX_DESC_PER_TX_PKT (MAX_BDS_PER_TX_PKT + \ 621#define MAX_DESC_PER_TX_PKT (MAX_BDS_PER_TX_PKT + \
@@ -731,16 +732,22 @@ struct bnx2x_fastpath {
731 732
732#define pbd_tcp_flags(tcp_hdr) (ntohl(tcp_flag_word(tcp_hdr))>>16 & 0xff) 733#define pbd_tcp_flags(tcp_hdr) (ntohl(tcp_flag_word(tcp_hdr))>>16 & 0xff)
733 734
734#define XMIT_PLAIN 0 735#define XMIT_PLAIN 0
735#define XMIT_CSUM_V4 0x1 736#define XMIT_CSUM_V4 (1 << 0)
736#define XMIT_CSUM_V6 0x2 737#define XMIT_CSUM_V6 (1 << 1)
737#define XMIT_CSUM_TCP 0x4 738#define XMIT_CSUM_TCP (1 << 2)
738#define XMIT_GSO_V4 0x8 739#define XMIT_GSO_V4 (1 << 3)
739#define XMIT_GSO_V6 0x10 740#define XMIT_GSO_V6 (1 << 4)
740 741#define XMIT_CSUM_ENC_V4 (1 << 5)
741#define XMIT_CSUM (XMIT_CSUM_V4 | XMIT_CSUM_V6) 742#define XMIT_CSUM_ENC_V6 (1 << 6)
742#define XMIT_GSO (XMIT_GSO_V4 | XMIT_GSO_V6) 743#define XMIT_GSO_ENC_V4 (1 << 7)
743 744#define XMIT_GSO_ENC_V6 (1 << 8)
745
746#define XMIT_CSUM_ENC (XMIT_CSUM_ENC_V4 | XMIT_CSUM_ENC_V6)
747#define XMIT_GSO_ENC (XMIT_GSO_ENC_V4 | XMIT_GSO_ENC_V6)
748
749#define XMIT_CSUM (XMIT_CSUM_V4 | XMIT_CSUM_V6 | XMIT_CSUM_ENC)
750#define XMIT_GSO (XMIT_GSO_V4 | XMIT_GSO_V6 | XMIT_GSO_ENC)
744 751
745/* stuff added to make the code fit 80Col */ 752/* stuff added to make the code fit 80Col */
746#define CQE_TYPE(cqe_fp_flags) ((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE) 753#define CQE_TYPE(cqe_fp_flags) ((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 9f7a3793590b..8091de70a539 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -3148,27 +3148,44 @@ static __le16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix)
3148static u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) 3148static u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb)
3149{ 3149{
3150 u32 rc; 3150 u32 rc;
3151 __u8 prot = 0;
3152 __be16 protocol;
3151 3153
3152 if (skb->ip_summed != CHECKSUM_PARTIAL) 3154 if (skb->ip_summed != CHECKSUM_PARTIAL)
3153 rc = XMIT_PLAIN; 3155 return XMIT_PLAIN;
3154 3156
3155 else { 3157 protocol = vlan_get_protocol(skb);
3156 if (vlan_get_protocol(skb) == htons(ETH_P_IPV6)) { 3158 if (protocol == htons(ETH_P_IPV6)) {
3157 rc = XMIT_CSUM_V6; 3159 rc = XMIT_CSUM_V6;
3158 if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) 3160 prot = ipv6_hdr(skb)->nexthdr;
3159 rc |= XMIT_CSUM_TCP; 3161 } else {
3162 rc = XMIT_CSUM_V4;
3163 prot = ip_hdr(skb)->protocol;
3164 }
3160 3165
3166 if (!CHIP_IS_E1x(bp) && skb->encapsulation) {
3167 if (inner_ip_hdr(skb)->version == 6) {
3168 rc |= XMIT_CSUM_ENC_V6;
3169 if (inner_ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
3170 rc |= XMIT_CSUM_TCP;
3161 } else { 3171 } else {
3162 rc = XMIT_CSUM_V4; 3172 rc |= XMIT_CSUM_ENC_V4;
3163 if (ip_hdr(skb)->protocol == IPPROTO_TCP) 3173 if (inner_ip_hdr(skb)->protocol == IPPROTO_TCP)
3164 rc |= XMIT_CSUM_TCP; 3174 rc |= XMIT_CSUM_TCP;
3165 } 3175 }
3166 } 3176 }
3177 if (prot == IPPROTO_TCP)
3178 rc |= XMIT_CSUM_TCP;
3167 3179
3168 if (skb_is_gso_v6(skb)) 3180 if (skb_is_gso_v6(skb)) {
3169 rc |= XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6; 3181 rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6);
3170 else if (skb_is_gso(skb)) 3182 if (rc & XMIT_CSUM_ENC)
3171 rc |= XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP; 3183 rc |= XMIT_GSO_ENC_V6;
3184 } else if (skb_is_gso(skb)) {
3185 rc |= (XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP);
3186 if (rc & XMIT_CSUM_ENC)
3187 rc |= XMIT_GSO_ENC_V4;
3188 }
3172 3189
3173 return rc; 3190 return rc;
3174} 3191}
@@ -3256,11 +3273,20 @@ exit_lbl:
3256static void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data, 3273static void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data,
3257 u32 xmit_type) 3274 u32 xmit_type)
3258{ 3275{
3276 struct ipv6hdr *ipv6;
3277
3259 *parsing_data |= (skb_shinfo(skb)->gso_size << 3278 *parsing_data |= (skb_shinfo(skb)->gso_size <<
3260 ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT) & 3279 ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT) &
3261 ETH_TX_PARSE_BD_E2_LSO_MSS; 3280 ETH_TX_PARSE_BD_E2_LSO_MSS;
3262 if ((xmit_type & XMIT_GSO_V6) && 3281
3263 (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6)) 3282 if (xmit_type & XMIT_GSO_ENC_V6)
3283 ipv6 = inner_ipv6_hdr(skb);
3284 else if (xmit_type & XMIT_GSO_V6)
3285 ipv6 = ipv6_hdr(skb);
3286 else
3287 ipv6 = NULL;
3288
3289 if (ipv6 && ipv6->nexthdr == NEXTHDR_IPV6)
3264 *parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR; 3290 *parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
3265} 3291}
3266 3292
@@ -3297,6 +3323,40 @@ static void bnx2x_set_pbd_gso(struct sk_buff *skb,
3297} 3323}
3298 3324
3299/** 3325/**
3326 * bnx2x_set_pbd_csum_enc - update PBD with checksum and return header length
3327 *
3328 * @bp: driver handle
3329 * @skb: packet skb
3330 * @parsing_data: data to be updated
3331 * @xmit_type: xmit flags
3332 *
3333 * 57712/578xx related, when skb has encapsulation
3334 */
3335static u8 bnx2x_set_pbd_csum_enc(struct bnx2x *bp, struct sk_buff *skb,
3336 u32 *parsing_data, u32 xmit_type)
3337{
3338 *parsing_data |=
3339 ((((u8 *)skb_inner_transport_header(skb) - skb->data) >> 1) <<
3340 ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W_SHIFT) &
3341 ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W;
3342
3343 if (xmit_type & XMIT_CSUM_TCP) {
3344 *parsing_data |= ((inner_tcp_hdrlen(skb) / 4) <<
3345 ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
3346 ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
3347
3348 return skb_inner_transport_header(skb) +
3349 inner_tcp_hdrlen(skb) - skb->data;
3350 }
3351
3352 /* We support checksum offload for TCP and UDP only.
3353 * No need to pass the UDP header length - it's a constant.
3354 */
3355 return skb_inner_transport_header(skb) +
3356 sizeof(struct udphdr) - skb->data;
3357}
3358
3359/**
3300 * bnx2x_set_pbd_csum_e2 - update PBD with checksum and return header length 3360 * bnx2x_set_pbd_csum_e2 - update PBD with checksum and return header length
3301 * 3361 *
3302 * @bp: driver handle 3362 * @bp: driver handle
@@ -3327,13 +3387,14 @@ static u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
3327 return skb_transport_header(skb) + sizeof(struct udphdr) - skb->data; 3387 return skb_transport_header(skb) + sizeof(struct udphdr) - skb->data;
3328} 3388}
3329 3389
3390/* set FW indication according to inner or outer protocols if tunneled */
3330static void bnx2x_set_sbd_csum(struct bnx2x *bp, struct sk_buff *skb, 3391static void bnx2x_set_sbd_csum(struct bnx2x *bp, struct sk_buff *skb,
3331 struct eth_tx_start_bd *tx_start_bd, 3392 struct eth_tx_start_bd *tx_start_bd,
3332 u32 xmit_type) 3393 u32 xmit_type)
3333{ 3394{
3334 tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM; 3395 tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
3335 3396
3336 if (xmit_type & XMIT_CSUM_V6) 3397 if (xmit_type & (XMIT_CSUM_ENC_V6 | XMIT_CSUM_V6))
3337 tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IPV6; 3398 tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IPV6;
3338 3399
3339 if (!(xmit_type & XMIT_CSUM_TCP)) 3400 if (!(xmit_type & XMIT_CSUM_TCP))
@@ -3396,6 +3457,72 @@ static u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
3396 return hlen; 3457 return hlen;
3397} 3458}
3398 3459
3460static void bnx2x_update_pbds_gso_enc(struct sk_buff *skb,
3461 struct eth_tx_parse_bd_e2 *pbd_e2,
3462 struct eth_tx_parse_2nd_bd *pbd2,
3463 u16 *global_data,
3464 u32 xmit_type)
3465{
3466 u16 inner_hlen_w = 0;
3467 u8 outerip_off, outerip_len = 0;
3468
3469 /* IP len */
3470 inner_hlen_w = (skb_inner_transport_header(skb) -
3471 skb_inner_network_header(skb)) >> 1;
3472
3473 /* transport len */
3474 if (xmit_type & XMIT_CSUM_TCP)
3475 inner_hlen_w += inner_tcp_hdrlen(skb) >> 1;
3476 else
3477 inner_hlen_w += sizeof(struct udphdr) >> 1;
3478
3479 pbd2->fw_ip_hdr_to_payload_w = inner_hlen_w;
3480
3481 if (xmit_type & XMIT_CSUM_ENC_V4) {
3482 struct iphdr *iph = inner_ip_hdr(skb);
3483
3484 pbd2->fw_ip_csum_wo_len_flags_frag =
3485 bswab16(csum_fold((~iph->check) -
3486 iph->tot_len - iph->frag_off));
3487 } else {
3488 pbd2->fw_ip_hdr_to_payload_w =
3489 inner_hlen_w - ((sizeof(struct ipv6hdr)) >> 1);
3490 }
3491
3492 pbd2->tcp_send_seq = bswab32(inner_tcp_hdr(skb)->seq);
3493
3494 pbd2->tcp_flags = pbd_tcp_flags(inner_tcp_hdr(skb));
3495
3496 if (xmit_type & XMIT_GSO_V4) {
3497 pbd2->hw_ip_id = bswab16(ip_hdr(skb)->id);
3498
3499 pbd_e2->data.tunnel_data.pseudo_csum =
3500 bswab16(~csum_tcpudp_magic(
3501 inner_ip_hdr(skb)->saddr,
3502 inner_ip_hdr(skb)->daddr,
3503 0, IPPROTO_TCP, 0));
3504
3505 outerip_len = ip_hdr(skb)->ihl << 1;
3506 } else {
3507 pbd_e2->data.tunnel_data.pseudo_csum =
3508 bswab16(~csum_ipv6_magic(
3509 &inner_ipv6_hdr(skb)->saddr,
3510 &inner_ipv6_hdr(skb)->daddr,
3511 0, IPPROTO_TCP, 0));
3512 }
3513
3514 outerip_off = (skb_network_header(skb) - skb->data) >> 1;
3515
3516 *global_data |=
3517 outerip_off |
3518 (!!(xmit_type & XMIT_CSUM_V6) <<
3519 ETH_TX_PARSE_2ND_BD_IP_HDR_TYPE_OUTER_SHIFT) |
3520 (outerip_len <<
3521 ETH_TX_PARSE_2ND_BD_IP_HDR_LEN_OUTER_W_SHIFT) |
3522 ((skb->protocol == cpu_to_be16(ETH_P_8021Q)) <<
3523 ETH_TX_PARSE_2ND_BD_LLC_SNAP_EN_SHIFT);
3524}
3525
3399/* called with netif_tx_lock 3526/* called with netif_tx_lock
3400 * bnx2x_tx_int() runs without netif_tx_lock unless it needs to call 3527 * bnx2x_tx_int() runs without netif_tx_lock unless it needs to call
3401 * netif_wake_queue() 3528 * netif_wake_queue()
@@ -3411,6 +3538,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
3411 struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL; 3538 struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
3412 struct eth_tx_parse_bd_e1x *pbd_e1x = NULL; 3539 struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
3413 struct eth_tx_parse_bd_e2 *pbd_e2 = NULL; 3540 struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
3541 struct eth_tx_parse_2nd_bd *pbd2 = NULL;
3414 u32 pbd_e2_parsing_data = 0; 3542 u32 pbd_e2_parsing_data = 0;
3415 u16 pkt_prod, bd_prod; 3543 u16 pkt_prod, bd_prod;
3416 int nbd, txq_index; 3544 int nbd, txq_index;
@@ -3567,12 +3695,46 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
3567 if (!CHIP_IS_E1x(bp)) { 3695 if (!CHIP_IS_E1x(bp)) {
3568 pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2; 3696 pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2;
3569 memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2)); 3697 memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
3570 /* Set PBD in checksum offload case */ 3698
3571 if (xmit_type & XMIT_CSUM) 3699 if (xmit_type & XMIT_CSUM_ENC) {
3700 u16 global_data = 0;
3701
3702 /* Set PBD in enc checksum offload case */
3703 hlen = bnx2x_set_pbd_csum_enc(bp, skb,
3704 &pbd_e2_parsing_data,
3705 xmit_type);
3706
3707 /* turn on 2nd parsing and get a BD */
3708 bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
3709
3710 pbd2 = &txdata->tx_desc_ring[bd_prod].parse_2nd_bd;
3711
3712 memset(pbd2, 0, sizeof(*pbd2));
3713
3714 pbd_e2->data.tunnel_data.ip_hdr_start_inner_w =
3715 (skb_inner_network_header(skb) -
3716 skb->data) >> 1;
3717
3718 if (xmit_type & XMIT_GSO_ENC)
3719 bnx2x_update_pbds_gso_enc(skb, pbd_e2, pbd2,
3720 &global_data,
3721 xmit_type);
3722
3723 pbd2->global_data = cpu_to_le16(global_data);
3724
3725 /* add addition parse BD indication to start BD */
3726 SET_FLAG(tx_start_bd->general_data,
3727 ETH_TX_START_BD_PARSE_NBDS, 1);
3728 /* set encapsulation flag in start BD */
3729 SET_FLAG(tx_start_bd->general_data,
3730 ETH_TX_START_BD_TUNNEL_EXIST, 1);
3731 nbd++;
3732 } else if (xmit_type & XMIT_CSUM) {
3572 /* Set PBD in checksum offload case w/o encapsulation */ 3733 /* Set PBD in checksum offload case w/o encapsulation */
3573 hlen = bnx2x_set_pbd_csum_e2(bp, skb, 3734 hlen = bnx2x_set_pbd_csum_e2(bp, skb,
3574 &pbd_e2_parsing_data, 3735 &pbd_e2_parsing_data,
3575 xmit_type); 3736 xmit_type);
3737 }
3576 3738
3577 /* Add the macs to the parsing BD this is a vf */ 3739 /* Add the macs to the parsing BD this is a vf */
3578 if (IS_VF(bp)) { 3740 if (IS_VF(bp)) {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 04d123ff11a2..4902d1eb3d1e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -11965,6 +11965,13 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
11965 NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | 11965 NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
11966 NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO | 11966 NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO |
11967 NETIF_F_RXHASH | NETIF_F_HW_VLAN_TX; 11967 NETIF_F_RXHASH | NETIF_F_HW_VLAN_TX;
11968 if (!CHIP_IS_E1x(bp)) {
11969 dev->hw_features |= NETIF_F_GSO_GRE;
11970 dev->hw_enc_features =
11971 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
11972 NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
11973 NETIF_F_GSO_GRE;
11974 }
11968 11975
11969 dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | 11976 dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
11970 NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA; 11977 NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;