diff options
author | Sreenivasa Honnur <Sreenivasa.Honnur@neterion.com> | 2008-02-20 17:09:15 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-03-17 07:49:26 -0400 |
commit | cdb5bf02f4fc0507518ea6b93c21b2707336ffef (patch) | |
tree | f750a05ea98b9f4ef3263b69b956fb26b80a15db /drivers/net/s2io.c | |
parent | 6cfc482b4b1c512d81712eba41fa324b24e5e7b2 (diff) |
S2io: Support for vlan_rx_kill_vid entry point
- Resubmit #3
- Added s2io_vlan_rx_kill_vid entry point function for unregistering vlan.
- Fix to aggregate vlan packets. IP offset is incremented by
4 bytes if the packet contains vlan header.
Signed-off-by: Surjit Reang <surjit.reang@neterion.com>
Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/s2io.c')
-rw-r--r-- | drivers/net/s2io.c | 115 |
1 files changed, 67 insertions, 48 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 9786de9c0248..0d65aaee6637 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
@@ -388,6 +388,26 @@ static void s2io_vlan_rx_register(struct net_device *dev, | |||
388 | /* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */ | 388 | /* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */ |
389 | static int vlan_strip_flag; | 389 | static int vlan_strip_flag; |
390 | 390 | ||
391 | /* Unregister the vlan */ | ||
392 | static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid) | ||
393 | { | ||
394 | int i; | ||
395 | struct s2io_nic *nic = dev->priv; | ||
396 | unsigned long flags[MAX_TX_FIFOS]; | ||
397 | struct mac_info *mac_control = &nic->mac_control; | ||
398 | struct config_param *config = &nic->config; | ||
399 | |||
400 | for (i = 0; i < config->tx_fifo_num; i++) | ||
401 | spin_lock_irqsave(&mac_control->fifos[i].tx_lock, flags[i]); | ||
402 | |||
403 | if (nic->vlgrp) | ||
404 | vlan_group_set_device(nic->vlgrp, vid, NULL); | ||
405 | |||
406 | for (i = config->tx_fifo_num - 1; i >= 0; i--) | ||
407 | spin_unlock_irqrestore(&mac_control->fifos[i].tx_lock, | ||
408 | flags[i]); | ||
409 | } | ||
410 | |||
391 | /* | 411 | /* |
392 | * Constants to be programmed into the Xena's registers, to configure | 412 | * Constants to be programmed into the Xena's registers, to configure |
393 | * the XAUI. | 413 | * the XAUI. |
@@ -3047,7 +3067,7 @@ static void rx_intr_handler(struct ring_info *ring_data) | |||
3047 | struct lro *lro = &nic->lro0_n[i]; | 3067 | struct lro *lro = &nic->lro0_n[i]; |
3048 | if (lro->in_use) { | 3068 | if (lro->in_use) { |
3049 | update_L3L4_header(nic, lro); | 3069 | update_L3L4_header(nic, lro); |
3050 | queue_rx_frame(lro->parent); | 3070 | queue_rx_frame(lro->parent, lro->vlan_tag); |
3051 | clear_lro_session(lro); | 3071 | clear_lro_session(lro); |
3052 | } | 3072 | } |
3053 | } | 3073 | } |
@@ -7522,7 +7542,8 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) | |||
7522 | { | 7542 | { |
7523 | lro_append_pkt(sp, lro, | 7543 | lro_append_pkt(sp, lro, |
7524 | skb, tcp_len); | 7544 | skb, tcp_len); |
7525 | queue_rx_frame(lro->parent); | 7545 | queue_rx_frame(lro->parent, |
7546 | lro->vlan_tag); | ||
7526 | clear_lro_session(lro); | 7547 | clear_lro_session(lro); |
7527 | sp->mac_control.stats_info-> | 7548 | sp->mac_control.stats_info-> |
7528 | sw_stat.flush_max_pkts++; | 7549 | sw_stat.flush_max_pkts++; |
@@ -7533,7 +7554,8 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) | |||
7533 | lro->frags_len; | 7554 | lro->frags_len; |
7534 | sp->mac_control.stats_info-> | 7555 | sp->mac_control.stats_info-> |
7535 | sw_stat.sending_both++; | 7556 | sw_stat.sending_both++; |
7536 | queue_rx_frame(lro->parent); | 7557 | queue_rx_frame(lro->parent, |
7558 | lro->vlan_tag); | ||
7537 | clear_lro_session(lro); | 7559 | clear_lro_session(lro); |
7538 | goto send_up; | 7560 | goto send_up; |
7539 | case 0: /* sessions exceeded */ | 7561 | case 0: /* sessions exceeded */ |
@@ -7559,31 +7581,12 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) | |||
7559 | */ | 7581 | */ |
7560 | skb->ip_summed = CHECKSUM_NONE; | 7582 | skb->ip_summed = CHECKSUM_NONE; |
7561 | } | 7583 | } |
7562 | } else { | 7584 | } else |
7563 | skb->ip_summed = CHECKSUM_NONE; | 7585 | skb->ip_summed = CHECKSUM_NONE; |
7564 | } | 7586 | |
7565 | sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize; | 7587 | sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize; |
7566 | if (!sp->lro) { | ||
7567 | skb->protocol = eth_type_trans(skb, dev); | ||
7568 | if ((sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2) && | ||
7569 | vlan_strip_flag)) { | ||
7570 | /* Queueing the vlan frame to the upper layer */ | ||
7571 | if (napi) | ||
7572 | vlan_hwaccel_receive_skb(skb, sp->vlgrp, | ||
7573 | RXD_GET_VLAN_TAG(rxdp->Control_2)); | ||
7574 | else | ||
7575 | vlan_hwaccel_rx(skb, sp->vlgrp, | ||
7576 | RXD_GET_VLAN_TAG(rxdp->Control_2)); | ||
7577 | } else { | ||
7578 | if (napi) | ||
7579 | netif_receive_skb(skb); | ||
7580 | else | ||
7581 | netif_rx(skb); | ||
7582 | } | ||
7583 | } else { | ||
7584 | send_up: | 7588 | send_up: |
7585 | queue_rx_frame(skb); | 7589 | queue_rx_frame(skb, RXD_GET_VLAN_TAG(rxdp->Control_2)); |
7586 | } | ||
7587 | dev->last_rx = jiffies; | 7590 | dev->last_rx = jiffies; |
7588 | aggregate: | 7591 | aggregate: |
7589 | atomic_dec(&sp->rx_bufs_left[ring_no]); | 7592 | atomic_dec(&sp->rx_bufs_left[ring_no]); |
@@ -8005,6 +8008,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) | |||
8005 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 8008 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
8006 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | 8009 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; |
8007 | dev->vlan_rx_register = s2io_vlan_rx_register; | 8010 | dev->vlan_rx_register = s2io_vlan_rx_register; |
8011 | dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid; | ||
8008 | 8012 | ||
8009 | /* | 8013 | /* |
8010 | * will use eth_mac_addr() for dev->set_mac_address | 8014 | * will use eth_mac_addr() for dev->set_mac_address |
@@ -8306,7 +8310,8 @@ module_init(s2io_starter); | |||
8306 | module_exit(s2io_closer); | 8310 | module_exit(s2io_closer); |
8307 | 8311 | ||
8308 | static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, | 8312 | static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, |
8309 | struct tcphdr **tcp, struct RxD_t *rxdp) | 8313 | struct tcphdr **tcp, struct RxD_t *rxdp, |
8314 | struct s2io_nic *sp) | ||
8310 | { | 8315 | { |
8311 | int ip_off; | 8316 | int ip_off; |
8312 | u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len; | 8317 | u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len; |
@@ -8317,19 +8322,20 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, | |||
8317 | return -1; | 8322 | return -1; |
8318 | } | 8323 | } |
8319 | 8324 | ||
8320 | /* TODO: | 8325 | /* Checking for DIX type or DIX type with VLAN */ |
8321 | * By default the VLAN field in the MAC is stripped by the card, if this | 8326 | if ((l2_type == 0) |
8322 | * feature is turned off in rx_pa_cfg register, then the ip_off field | 8327 | || (l2_type == 4)) { |
8323 | * has to be shifted by a further 2 bytes | 8328 | ip_off = HEADER_ETHERNET_II_802_3_SIZE; |
8324 | */ | 8329 | /* |
8325 | switch (l2_type) { | 8330 | * If vlan stripping is disabled and the frame is VLAN tagged, |
8326 | case 0: /* DIX type */ | 8331 | * shift the offset by the VLAN header size bytes. |
8327 | case 4: /* DIX type with VLAN */ | 8332 | */ |
8328 | ip_off = HEADER_ETHERNET_II_802_3_SIZE; | 8333 | if ((!vlan_strip_flag) && |
8329 | break; | 8334 | (rxdp->Control_1 & RXD_FRAME_VLAN_TAG)) |
8335 | ip_off += HEADER_VLAN_SIZE; | ||
8336 | } else { | ||
8330 | /* LLC, SNAP etc are considered non-mergeable */ | 8337 | /* LLC, SNAP etc are considered non-mergeable */ |
8331 | default: | 8338 | return -1; |
8332 | return -1; | ||
8333 | } | 8339 | } |
8334 | 8340 | ||
8335 | *ip = (struct iphdr *)((u8 *)buffer + ip_off); | 8341 | *ip = (struct iphdr *)((u8 *)buffer + ip_off); |
@@ -8356,7 +8362,7 @@ static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp) | |||
8356 | } | 8362 | } |
8357 | 8363 | ||
8358 | static void initiate_new_session(struct lro *lro, u8 *l2h, | 8364 | static void initiate_new_session(struct lro *lro, u8 *l2h, |
8359 | struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len) | 8365 | struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len, u16 vlan_tag) |
8360 | { | 8366 | { |
8361 | DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); | 8367 | DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); |
8362 | lro->l2h = l2h; | 8368 | lro->l2h = l2h; |
@@ -8367,6 +8373,7 @@ static void initiate_new_session(struct lro *lro, u8 *l2h, | |||
8367 | lro->sg_num = 1; | 8373 | lro->sg_num = 1; |
8368 | lro->total_len = ntohs(ip->tot_len); | 8374 | lro->total_len = ntohs(ip->tot_len); |
8369 | lro->frags_len = 0; | 8375 | lro->frags_len = 0; |
8376 | lro->vlan_tag = vlan_tag; | ||
8370 | /* | 8377 | /* |
8371 | * check if we saw TCP timestamp. Other consistency checks have | 8378 | * check if we saw TCP timestamp. Other consistency checks have |
8372 | * already been done. | 8379 | * already been done. |
@@ -8498,15 +8505,16 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro, | |||
8498 | struct iphdr *ip; | 8505 | struct iphdr *ip; |
8499 | struct tcphdr *tcph; | 8506 | struct tcphdr *tcph; |
8500 | int ret = 0, i; | 8507 | int ret = 0, i; |
8508 | u16 vlan_tag = 0; | ||
8501 | 8509 | ||
8502 | if (!(ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp, | 8510 | if (!(ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp, |
8503 | rxdp))) { | 8511 | rxdp, sp))) { |
8504 | DBG_PRINT(INFO_DBG,"IP Saddr: %x Daddr: %x\n", | 8512 | DBG_PRINT(INFO_DBG,"IP Saddr: %x Daddr: %x\n", |
8505 | ip->saddr, ip->daddr); | 8513 | ip->saddr, ip->daddr); |
8506 | } else { | 8514 | } else |
8507 | return ret; | 8515 | return ret; |
8508 | } | ||
8509 | 8516 | ||
8517 | vlan_tag = RXD_GET_VLAN_TAG(rxdp->Control_2); | ||
8510 | tcph = (struct tcphdr *)*tcp; | 8518 | tcph = (struct tcphdr *)*tcp; |
8511 | *tcp_len = get_l4_pyld_length(ip, tcph); | 8519 | *tcp_len = get_l4_pyld_length(ip, tcph); |
8512 | for (i=0; i<MAX_LRO_SESSIONS; i++) { | 8520 | for (i=0; i<MAX_LRO_SESSIONS; i++) { |
@@ -8566,7 +8574,8 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro, | |||
8566 | 8574 | ||
8567 | switch (ret) { | 8575 | switch (ret) { |
8568 | case 3: | 8576 | case 3: |
8569 | initiate_new_session(*lro, buffer, ip, tcph, *tcp_len); | 8577 | initiate_new_session(*lro, buffer, ip, tcph, *tcp_len, |
8578 | vlan_tag); | ||
8570 | break; | 8579 | break; |
8571 | case 2: | 8580 | case 2: |
8572 | update_L3L4_header(sp, *lro); | 8581 | update_L3L4_header(sp, *lro); |
@@ -8594,15 +8603,25 @@ static void clear_lro_session(struct lro *lro) | |||
8594 | memset(lro, 0, lro_struct_size); | 8603 | memset(lro, 0, lro_struct_size); |
8595 | } | 8604 | } |
8596 | 8605 | ||
8597 | static void queue_rx_frame(struct sk_buff *skb) | 8606 | static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag) |
8598 | { | 8607 | { |
8599 | struct net_device *dev = skb->dev; | 8608 | struct net_device *dev = skb->dev; |
8609 | struct s2io_nic *sp = dev->priv; | ||
8600 | 8610 | ||
8601 | skb->protocol = eth_type_trans(skb, dev); | 8611 | skb->protocol = eth_type_trans(skb, dev); |
8602 | if (napi) | 8612 | if (sp->vlgrp && vlan_tag |
8603 | netif_receive_skb(skb); | 8613 | && (vlan_strip_flag)) { |
8604 | else | 8614 | /* Queueing the vlan frame to the upper layer */ |
8605 | netif_rx(skb); | 8615 | if (sp->config.napi) |
8616 | vlan_hwaccel_receive_skb(skb, sp->vlgrp, vlan_tag); | ||
8617 | else | ||
8618 | vlan_hwaccel_rx(skb, sp->vlgrp, vlan_tag); | ||
8619 | } else { | ||
8620 | if (sp->config.napi) | ||
8621 | netif_receive_skb(skb); | ||
8622 | else | ||
8623 | netif_rx(skb); | ||
8624 | } | ||
8606 | } | 8625 | } |
8607 | 8626 | ||
8608 | static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro, | 8627 | static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro, |