aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/s2io.c
diff options
context:
space:
mode:
authorSreenivasa Honnur <Sreenivasa.Honnur@neterion.com>2008-02-20 17:09:15 -0500
committerJeff Garzik <jeff@garzik.org>2008-03-17 07:49:26 -0400
commitcdb5bf02f4fc0507518ea6b93c21b2707336ffef (patch)
treef750a05ea98b9f4ef3263b69b956fb26b80a15db /drivers/net/s2io.c
parent6cfc482b4b1c512d81712eba41fa324b24e5e7b2 (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.c115
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 */
389static int vlan_strip_flag; 389static int vlan_strip_flag;
390 390
391/* Unregister the vlan */
392static 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 {
7584send_up: 7588send_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;
7588aggregate: 7591aggregate:
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);
8306module_exit(s2io_closer); 8310module_exit(s2io_closer);
8307 8311
8308static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, 8312static 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
8358static void initiate_new_session(struct lro *lro, u8 *l2h, 8364static 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
8597static void queue_rx_frame(struct sk_buff *skb) 8606static 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
8608static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro, 8627static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,