diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/skge.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r-- | drivers/net/skge.c | 155 |
1 files changed, 47 insertions, 108 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 465ae7e84507..f4be5c78ebfd 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/mii.h> | 44 | #include <linux/mii.h> |
45 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
46 | #include <linux/dmi.h> | 46 | #include <linux/dmi.h> |
47 | #include <linux/prefetch.h> | ||
47 | #include <asm/irq.h> | 48 | #include <asm/irq.h> |
48 | 49 | ||
49 | #include "skge.h" | 50 | #include "skge.h" |
@@ -303,7 +304,7 @@ static int skge_get_settings(struct net_device *dev, | |||
303 | 304 | ||
304 | ecmd->advertising = skge->advertising; | 305 | ecmd->advertising = skge->advertising; |
305 | ecmd->autoneg = skge->autoneg; | 306 | ecmd->autoneg = skge->autoneg; |
306 | ecmd->speed = skge->speed; | 307 | ethtool_cmd_speed_set(ecmd, skge->speed); |
307 | ecmd->duplex = skge->duplex; | 308 | ecmd->duplex = skge->duplex; |
308 | return 0; | 309 | return 0; |
309 | } | 310 | } |
@@ -321,8 +322,9 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
321 | skge->speed = -1; | 322 | skge->speed = -1; |
322 | } else { | 323 | } else { |
323 | u32 setting; | 324 | u32 setting; |
325 | u32 speed = ethtool_cmd_speed(ecmd); | ||
324 | 326 | ||
325 | switch (ecmd->speed) { | 327 | switch (speed) { |
326 | case SPEED_1000: | 328 | case SPEED_1000: |
327 | if (ecmd->duplex == DUPLEX_FULL) | 329 | if (ecmd->duplex == DUPLEX_FULL) |
328 | setting = SUPPORTED_1000baseT_Full; | 330 | setting = SUPPORTED_1000baseT_Full; |
@@ -355,7 +357,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
355 | if ((setting & supported) == 0) | 357 | if ((setting & supported) == 0) |
356 | return -EINVAL; | 358 | return -EINVAL; |
357 | 359 | ||
358 | skge->speed = ecmd->speed; | 360 | skge->speed = speed; |
359 | skge->duplex = ecmd->duplex; | 361 | skge->duplex = ecmd->duplex; |
360 | } | 362 | } |
361 | 363 | ||
@@ -537,46 +539,6 @@ static int skge_nway_reset(struct net_device *dev) | |||
537 | return 0; | 539 | return 0; |
538 | } | 540 | } |
539 | 541 | ||
540 | static int skge_set_sg(struct net_device *dev, u32 data) | ||
541 | { | ||
542 | struct skge_port *skge = netdev_priv(dev); | ||
543 | struct skge_hw *hw = skge->hw; | ||
544 | |||
545 | if (hw->chip_id == CHIP_ID_GENESIS && data) | ||
546 | return -EOPNOTSUPP; | ||
547 | return ethtool_op_set_sg(dev, data); | ||
548 | } | ||
549 | |||
550 | static int skge_set_tx_csum(struct net_device *dev, u32 data) | ||
551 | { | ||
552 | struct skge_port *skge = netdev_priv(dev); | ||
553 | struct skge_hw *hw = skge->hw; | ||
554 | |||
555 | if (hw->chip_id == CHIP_ID_GENESIS && data) | ||
556 | return -EOPNOTSUPP; | ||
557 | |||
558 | return ethtool_op_set_tx_csum(dev, data); | ||
559 | } | ||
560 | |||
561 | static u32 skge_get_rx_csum(struct net_device *dev) | ||
562 | { | ||
563 | struct skge_port *skge = netdev_priv(dev); | ||
564 | |||
565 | return skge->rx_csum; | ||
566 | } | ||
567 | |||
568 | /* Only Yukon supports checksum offload. */ | ||
569 | static int skge_set_rx_csum(struct net_device *dev, u32 data) | ||
570 | { | ||
571 | struct skge_port *skge = netdev_priv(dev); | ||
572 | |||
573 | if (skge->hw->chip_id == CHIP_ID_GENESIS && data) | ||
574 | return -EOPNOTSUPP; | ||
575 | |||
576 | skge->rx_csum = data; | ||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | static void skge_get_pauseparam(struct net_device *dev, | 542 | static void skge_get_pauseparam(struct net_device *dev, |
581 | struct ethtool_pauseparam *ecmd) | 543 | struct ethtool_pauseparam *ecmd) |
582 | { | 544 | { |
@@ -786,28 +748,27 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) | |||
786 | } | 748 | } |
787 | 749 | ||
788 | /* blink LED's for finding board */ | 750 | /* blink LED's for finding board */ |
789 | static int skge_phys_id(struct net_device *dev, u32 data) | 751 | static int skge_set_phys_id(struct net_device *dev, |
752 | enum ethtool_phys_id_state state) | ||
790 | { | 753 | { |
791 | struct skge_port *skge = netdev_priv(dev); | 754 | struct skge_port *skge = netdev_priv(dev); |
792 | unsigned long ms; | ||
793 | enum led_mode mode = LED_MODE_TST; | ||
794 | 755 | ||
795 | if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) | 756 | switch (state) { |
796 | ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000; | 757 | case ETHTOOL_ID_ACTIVE: |
797 | else | 758 | return 2; /* cycle on/off twice per second */ |
798 | ms = data * 1000; | ||
799 | 759 | ||
800 | while (ms > 0) { | 760 | case ETHTOOL_ID_ON: |
801 | skge_led(skge, mode); | 761 | skge_led(skge, LED_MODE_TST); |
802 | mode ^= LED_MODE_TST; | 762 | break; |
803 | 763 | ||
804 | if (msleep_interruptible(BLINK_MS)) | 764 | case ETHTOOL_ID_OFF: |
805 | break; | 765 | skge_led(skge, LED_MODE_OFF); |
806 | ms -= BLINK_MS; | 766 | break; |
807 | } | ||
808 | 767 | ||
809 | /* back to regular LED state */ | 768 | case ETHTOOL_ID_INACTIVE: |
810 | skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); | 769 | /* back to regular LED state */ |
770 | skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); | ||
771 | } | ||
811 | 772 | ||
812 | return 0; | 773 | return 0; |
813 | } | 774 | } |
@@ -925,12 +886,8 @@ static const struct ethtool_ops skge_ethtool_ops = { | |||
925 | .set_pauseparam = skge_set_pauseparam, | 886 | .set_pauseparam = skge_set_pauseparam, |
926 | .get_coalesce = skge_get_coalesce, | 887 | .get_coalesce = skge_get_coalesce, |
927 | .set_coalesce = skge_set_coalesce, | 888 | .set_coalesce = skge_set_coalesce, |
928 | .set_sg = skge_set_sg, | ||
929 | .set_tx_csum = skge_set_tx_csum, | ||
930 | .get_rx_csum = skge_get_rx_csum, | ||
931 | .set_rx_csum = skge_set_rx_csum, | ||
932 | .get_strings = skge_get_strings, | 889 | .get_strings = skge_get_strings, |
933 | .phys_id = skge_phys_id, | 890 | .set_phys_id = skge_set_phys_id, |
934 | .get_sset_count = skge_get_sset_count, | 891 | .get_sset_count = skge_get_sset_count, |
935 | .get_ethtool_stats = skge_get_ethtool_stats, | 892 | .get_ethtool_stats = skge_get_ethtool_stats, |
936 | }; | 893 | }; |
@@ -1191,7 +1148,7 @@ static void genesis_init(struct skge_hw *hw) | |||
1191 | 1148 | ||
1192 | static void genesis_reset(struct skge_hw *hw, int port) | 1149 | static void genesis_reset(struct skge_hw *hw, int port) |
1193 | { | 1150 | { |
1194 | const u8 zero[8] = { 0 }; | 1151 | static const u8 zero[8] = { 0 }; |
1195 | u32 reg; | 1152 | u32 reg; |
1196 | 1153 | ||
1197 | skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); | 1154 | skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); |
@@ -1557,7 +1514,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port) | |||
1557 | int jumbo = hw->dev[port]->mtu > ETH_DATA_LEN; | 1514 | int jumbo = hw->dev[port]->mtu > ETH_DATA_LEN; |
1558 | int i; | 1515 | int i; |
1559 | u32 r; | 1516 | u32 r; |
1560 | const u8 zero[6] = { 0 }; | 1517 | static const u8 zero[6] = { 0 }; |
1561 | 1518 | ||
1562 | for (i = 0; i < 10; i++) { | 1519 | for (i = 0; i < 10; i++) { |
1563 | skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), | 1520 | skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), |
@@ -2764,7 +2721,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, | |||
2764 | td->dma_hi = map >> 32; | 2721 | td->dma_hi = map >> 32; |
2765 | 2722 | ||
2766 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 2723 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
2767 | const int offset = skb_transport_offset(skb); | 2724 | const int offset = skb_checksum_start_offset(skb); |
2768 | 2725 | ||
2769 | /* This seems backwards, but it is what the sk98lin | 2726 | /* This seems backwards, but it is what the sk98lin |
2770 | * does. Looks like hardware is wrong? | 2727 | * does. Looks like hardware is wrong? |
@@ -3085,7 +3042,8 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, | |||
3085 | } | 3042 | } |
3086 | 3043 | ||
3087 | skb_put(skb, len); | 3044 | skb_put(skb, len); |
3088 | if (skge->rx_csum) { | 3045 | |
3046 | if (dev->features & NETIF_F_RXCSUM) { | ||
3089 | skb->csum = csum; | 3047 | skb->csum = csum; |
3090 | skb->ip_summed = CHECKSUM_COMPLETE; | 3048 | skb->ip_summed = CHECKSUM_COMPLETE; |
3091 | } | 3049 | } |
@@ -3179,8 +3137,7 @@ static int skge_poll(struct napi_struct *napi, int to_do) | |||
3179 | 3137 | ||
3180 | skb = skge_rx_get(dev, e, control, rd->status, rd->csum2); | 3138 | skb = skge_rx_get(dev, e, control, rd->status, rd->csum2); |
3181 | if (likely(skb)) { | 3139 | if (likely(skb)) { |
3182 | netif_receive_skb(skb); | 3140 | napi_gro_receive(napi, skb); |
3183 | |||
3184 | ++work_done; | 3141 | ++work_done; |
3185 | } | 3142 | } |
3186 | } | 3143 | } |
@@ -3193,6 +3150,7 @@ static int skge_poll(struct napi_struct *napi, int to_do) | |||
3193 | if (work_done < to_do) { | 3150 | if (work_done < to_do) { |
3194 | unsigned long flags; | 3151 | unsigned long flags; |
3195 | 3152 | ||
3153 | napi_gro_flush(napi); | ||
3196 | spin_lock_irqsave(&hw->hw_lock, flags); | 3154 | spin_lock_irqsave(&hw->hw_lock, flags); |
3197 | __napi_complete(napi); | 3155 | __napi_complete(napi); |
3198 | hw->intr_mask |= napimask[skge->port]; | 3156 | hw->intr_mask |= napimask[skge->port]; |
@@ -3847,18 +3805,15 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, | |||
3847 | setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge); | 3805 | setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge); |
3848 | 3806 | ||
3849 | if (hw->chip_id != CHIP_ID_GENESIS) { | 3807 | if (hw->chip_id != CHIP_ID_GENESIS) { |
3850 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | 3808 | dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | |
3851 | skge->rx_csum = 1; | 3809 | NETIF_F_RXCSUM; |
3810 | dev->features |= dev->hw_features; | ||
3852 | } | 3811 | } |
3853 | 3812 | ||
3854 | /* read the mac address */ | 3813 | /* read the mac address */ |
3855 | memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN); | 3814 | memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN); |
3856 | memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); | 3815 | memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); |
3857 | 3816 | ||
3858 | /* device is off until link detection */ | ||
3859 | netif_carrier_off(dev); | ||
3860 | netif_stop_queue(dev); | ||
3861 | |||
3862 | return dev; | 3817 | return dev; |
3863 | } | 3818 | } |
3864 | 3819 | ||
@@ -4012,8 +3967,6 @@ static void __devexit skge_remove(struct pci_dev *pdev) | |||
4012 | if (!hw) | 3967 | if (!hw) |
4013 | return; | 3968 | return; |
4014 | 3969 | ||
4015 | flush_scheduled_work(); | ||
4016 | |||
4017 | dev1 = hw->dev[1]; | 3970 | dev1 = hw->dev[1]; |
4018 | if (dev1) | 3971 | if (dev1) |
4019 | unregister_netdev(dev1); | 3972 | unregister_netdev(dev1); |
@@ -4044,53 +3997,40 @@ static void __devexit skge_remove(struct pci_dev *pdev) | |||
4044 | } | 3997 | } |
4045 | 3998 | ||
4046 | #ifdef CONFIG_PM | 3999 | #ifdef CONFIG_PM |
4047 | static int skge_suspend(struct pci_dev *pdev, pm_message_t state) | 4000 | static int skge_suspend(struct device *dev) |
4048 | { | 4001 | { |
4002 | struct pci_dev *pdev = to_pci_dev(dev); | ||
4049 | struct skge_hw *hw = pci_get_drvdata(pdev); | 4003 | struct skge_hw *hw = pci_get_drvdata(pdev); |
4050 | int i, err, wol = 0; | 4004 | int i; |
4051 | 4005 | ||
4052 | if (!hw) | 4006 | if (!hw) |
4053 | return 0; | 4007 | return 0; |
4054 | 4008 | ||
4055 | err = pci_save_state(pdev); | ||
4056 | if (err) | ||
4057 | return err; | ||
4058 | |||
4059 | for (i = 0; i < hw->ports; i++) { | 4009 | for (i = 0; i < hw->ports; i++) { |
4060 | struct net_device *dev = hw->dev[i]; | 4010 | struct net_device *dev = hw->dev[i]; |
4061 | struct skge_port *skge = netdev_priv(dev); | 4011 | struct skge_port *skge = netdev_priv(dev); |
4062 | 4012 | ||
4063 | if (netif_running(dev)) | 4013 | if (netif_running(dev)) |
4064 | skge_down(dev); | 4014 | skge_down(dev); |
4015 | |||
4065 | if (skge->wol) | 4016 | if (skge->wol) |
4066 | skge_wol_init(skge); | 4017 | skge_wol_init(skge); |
4067 | |||
4068 | wol |= skge->wol; | ||
4069 | } | 4018 | } |
4070 | 4019 | ||
4071 | skge_write32(hw, B0_IMSK, 0); | 4020 | skge_write32(hw, B0_IMSK, 0); |
4072 | 4021 | ||
4073 | pci_prepare_to_sleep(pdev); | ||
4074 | |||
4075 | return 0; | 4022 | return 0; |
4076 | } | 4023 | } |
4077 | 4024 | ||
4078 | static int skge_resume(struct pci_dev *pdev) | 4025 | static int skge_resume(struct device *dev) |
4079 | { | 4026 | { |
4027 | struct pci_dev *pdev = to_pci_dev(dev); | ||
4080 | struct skge_hw *hw = pci_get_drvdata(pdev); | 4028 | struct skge_hw *hw = pci_get_drvdata(pdev); |
4081 | int i, err; | 4029 | int i, err; |
4082 | 4030 | ||
4083 | if (!hw) | 4031 | if (!hw) |
4084 | return 0; | 4032 | return 0; |
4085 | 4033 | ||
4086 | err = pci_back_from_sleep(pdev); | ||
4087 | if (err) | ||
4088 | goto out; | ||
4089 | |||
4090 | err = pci_restore_state(pdev); | ||
4091 | if (err) | ||
4092 | goto out; | ||
4093 | |||
4094 | err = skge_reset(hw); | 4034 | err = skge_reset(hw); |
4095 | if (err) | 4035 | if (err) |
4096 | goto out; | 4036 | goto out; |
@@ -4111,12 +4051,19 @@ static int skge_resume(struct pci_dev *pdev) | |||
4111 | out: | 4051 | out: |
4112 | return err; | 4052 | return err; |
4113 | } | 4053 | } |
4054 | |||
4055 | static SIMPLE_DEV_PM_OPS(skge_pm_ops, skge_suspend, skge_resume); | ||
4056 | #define SKGE_PM_OPS (&skge_pm_ops) | ||
4057 | |||
4058 | #else | ||
4059 | |||
4060 | #define SKGE_PM_OPS NULL | ||
4114 | #endif | 4061 | #endif |
4115 | 4062 | ||
4116 | static void skge_shutdown(struct pci_dev *pdev) | 4063 | static void skge_shutdown(struct pci_dev *pdev) |
4117 | { | 4064 | { |
4118 | struct skge_hw *hw = pci_get_drvdata(pdev); | 4065 | struct skge_hw *hw = pci_get_drvdata(pdev); |
4119 | int i, wol = 0; | 4066 | int i; |
4120 | 4067 | ||
4121 | if (!hw) | 4068 | if (!hw) |
4122 | return; | 4069 | return; |
@@ -4127,15 +4074,10 @@ static void skge_shutdown(struct pci_dev *pdev) | |||
4127 | 4074 | ||
4128 | if (skge->wol) | 4075 | if (skge->wol) |
4129 | skge_wol_init(skge); | 4076 | skge_wol_init(skge); |
4130 | wol |= skge->wol; | ||
4131 | } | 4077 | } |
4132 | 4078 | ||
4133 | if (pci_enable_wake(pdev, PCI_D3cold, wol)) | 4079 | pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev)); |
4134 | pci_enable_wake(pdev, PCI_D3hot, wol); | ||
4135 | |||
4136 | pci_disable_device(pdev); | ||
4137 | pci_set_power_state(pdev, PCI_D3hot); | 4080 | pci_set_power_state(pdev, PCI_D3hot); |
4138 | |||
4139 | } | 4081 | } |
4140 | 4082 | ||
4141 | static struct pci_driver skge_driver = { | 4083 | static struct pci_driver skge_driver = { |
@@ -4143,11 +4085,8 @@ static struct pci_driver skge_driver = { | |||
4143 | .id_table = skge_id_table, | 4085 | .id_table = skge_id_table, |
4144 | .probe = skge_probe, | 4086 | .probe = skge_probe, |
4145 | .remove = __devexit_p(skge_remove), | 4087 | .remove = __devexit_p(skge_remove), |
4146 | #ifdef CONFIG_PM | ||
4147 | .suspend = skge_suspend, | ||
4148 | .resume = skge_resume, | ||
4149 | #endif | ||
4150 | .shutdown = skge_shutdown, | 4088 | .shutdown = skge_shutdown, |
4089 | .driver.pm = SKGE_PM_OPS, | ||
4151 | }; | 4090 | }; |
4152 | 4091 | ||
4153 | static struct dmi_system_id skge_32bit_dma_boards[] = { | 4092 | static struct dmi_system_id skge_32bit_dma_boards[] = { |