diff options
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/usb/asix.c | 28 | ||||
-rw-r--r-- | drivers/net/usb/catc.c | 2 | ||||
-rw-r--r-- | drivers/net/usb/dm9601.c | 6 | ||||
-rw-r--r-- | drivers/net/usb/plusb.c | 32 | ||||
-rw-r--r-- | drivers/net/usb/rndis_host.c | 39 | ||||
-rw-r--r-- | drivers/net/usb/rtl8150.c | 11 | ||||
-rw-r--r-- | drivers/net/usb/smsc75xx.c | 131 | ||||
-rw-r--r-- | drivers/net/usb/smsc95xx.c | 90 | ||||
-rw-r--r-- | drivers/net/usb/usbnet.c | 6 |
10 files changed, 159 insertions, 188 deletions
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 3ec22c307797..9d4f9117260f 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
@@ -258,7 +258,7 @@ config USB_NET_NET1080 | |||
258 | optionally with LEDs that indicate traffic | 258 | optionally with LEDs that indicate traffic |
259 | 259 | ||
260 | config USB_NET_PLUSB | 260 | config USB_NET_PLUSB |
261 | tristate "Prolific PL-2301/2302 based cables" | 261 | tristate "Prolific PL-2301/2302/25A1 based cables" |
262 | # if the handshake/init/reset problems, from original 'plusb', | 262 | # if the handshake/init/reset problems, from original 'plusb', |
263 | # are ever resolved ... then remove "experimental" | 263 | # are ever resolved ... then remove "experimental" |
264 | depends on USB_USBNET && EXPERIMENTAL | 264 | depends on USB_USBNET && EXPERIMENTAL |
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 6140b56cce53..6998aa6b7bb7 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c | |||
@@ -847,7 +847,7 @@ static void ax88172_set_multicast(struct net_device *net) | |||
847 | static int ax88172_link_reset(struct usbnet *dev) | 847 | static int ax88172_link_reset(struct usbnet *dev) |
848 | { | 848 | { |
849 | u8 mode; | 849 | u8 mode; |
850 | struct ethtool_cmd ecmd; | 850 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; |
851 | 851 | ||
852 | mii_check_media(&dev->mii, 1, 1); | 852 | mii_check_media(&dev->mii, 1, 1); |
853 | mii_ethtool_gset(&dev->mii, &ecmd); | 853 | mii_ethtool_gset(&dev->mii, &ecmd); |
@@ -856,8 +856,8 @@ static int ax88172_link_reset(struct usbnet *dev) | |||
856 | if (ecmd.duplex != DUPLEX_FULL) | 856 | if (ecmd.duplex != DUPLEX_FULL) |
857 | mode |= ~AX88172_MEDIUM_FD; | 857 | mode |= ~AX88172_MEDIUM_FD; |
858 | 858 | ||
859 | netdev_dbg(dev->net, "ax88172_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", | 859 | netdev_dbg(dev->net, "ax88172_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n", |
860 | ecmd.speed, ecmd.duplex, mode); | 860 | ethtool_cmd_speed(&ecmd), ecmd.duplex, mode); |
861 | 861 | ||
862 | asix_write_medium_mode(dev, mode); | 862 | asix_write_medium_mode(dev, mode); |
863 | 863 | ||
@@ -947,20 +947,20 @@ static const struct ethtool_ops ax88772_ethtool_ops = { | |||
947 | static int ax88772_link_reset(struct usbnet *dev) | 947 | static int ax88772_link_reset(struct usbnet *dev) |
948 | { | 948 | { |
949 | u16 mode; | 949 | u16 mode; |
950 | struct ethtool_cmd ecmd; | 950 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; |
951 | 951 | ||
952 | mii_check_media(&dev->mii, 1, 1); | 952 | mii_check_media(&dev->mii, 1, 1); |
953 | mii_ethtool_gset(&dev->mii, &ecmd); | 953 | mii_ethtool_gset(&dev->mii, &ecmd); |
954 | mode = AX88772_MEDIUM_DEFAULT; | 954 | mode = AX88772_MEDIUM_DEFAULT; |
955 | 955 | ||
956 | if (ecmd.speed != SPEED_100) | 956 | if (ethtool_cmd_speed(&ecmd) != SPEED_100) |
957 | mode &= ~AX_MEDIUM_PS; | 957 | mode &= ~AX_MEDIUM_PS; |
958 | 958 | ||
959 | if (ecmd.duplex != DUPLEX_FULL) | 959 | if (ecmd.duplex != DUPLEX_FULL) |
960 | mode &= ~AX_MEDIUM_FD; | 960 | mode &= ~AX_MEDIUM_FD; |
961 | 961 | ||
962 | netdev_dbg(dev->net, "ax88772_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", | 962 | netdev_dbg(dev->net, "ax88772_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n", |
963 | ecmd.speed, ecmd.duplex, mode); | 963 | ethtool_cmd_speed(&ecmd), ecmd.duplex, mode); |
964 | 964 | ||
965 | asix_write_medium_mode(dev, mode); | 965 | asix_write_medium_mode(dev, mode); |
966 | 966 | ||
@@ -1173,18 +1173,20 @@ static int marvell_led_status(struct usbnet *dev, u16 speed) | |||
1173 | static int ax88178_link_reset(struct usbnet *dev) | 1173 | static int ax88178_link_reset(struct usbnet *dev) |
1174 | { | 1174 | { |
1175 | u16 mode; | 1175 | u16 mode; |
1176 | struct ethtool_cmd ecmd; | 1176 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; |
1177 | struct asix_data *data = (struct asix_data *)&dev->data; | 1177 | struct asix_data *data = (struct asix_data *)&dev->data; |
1178 | u32 speed; | ||
1178 | 1179 | ||
1179 | netdev_dbg(dev->net, "ax88178_link_reset()\n"); | 1180 | netdev_dbg(dev->net, "ax88178_link_reset()\n"); |
1180 | 1181 | ||
1181 | mii_check_media(&dev->mii, 1, 1); | 1182 | mii_check_media(&dev->mii, 1, 1); |
1182 | mii_ethtool_gset(&dev->mii, &ecmd); | 1183 | mii_ethtool_gset(&dev->mii, &ecmd); |
1183 | mode = AX88178_MEDIUM_DEFAULT; | 1184 | mode = AX88178_MEDIUM_DEFAULT; |
1185 | speed = ethtool_cmd_speed(&ecmd); | ||
1184 | 1186 | ||
1185 | if (ecmd.speed == SPEED_1000) | 1187 | if (speed == SPEED_1000) |
1186 | mode |= AX_MEDIUM_GM; | 1188 | mode |= AX_MEDIUM_GM; |
1187 | else if (ecmd.speed == SPEED_100) | 1189 | else if (speed == SPEED_100) |
1188 | mode |= AX_MEDIUM_PS; | 1190 | mode |= AX_MEDIUM_PS; |
1189 | else | 1191 | else |
1190 | mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM); | 1192 | mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM); |
@@ -1196,13 +1198,13 @@ static int ax88178_link_reset(struct usbnet *dev) | |||
1196 | else | 1198 | else |
1197 | mode &= ~AX_MEDIUM_FD; | 1199 | mode &= ~AX_MEDIUM_FD; |
1198 | 1200 | ||
1199 | netdev_dbg(dev->net, "ax88178_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", | 1201 | netdev_dbg(dev->net, "ax88178_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n", |
1200 | ecmd.speed, ecmd.duplex, mode); | 1202 | speed, ecmd.duplex, mode); |
1201 | 1203 | ||
1202 | asix_write_medium_mode(dev, mode); | 1204 | asix_write_medium_mode(dev, mode); |
1203 | 1205 | ||
1204 | if (data->phymode == PHY_MODE_MARVELL && data->ledmode) | 1206 | if (data->phymode == PHY_MODE_MARVELL && data->ledmode) |
1205 | marvell_led_status(dev, ecmd.speed); | 1207 | marvell_led_status(dev, speed); |
1206 | 1208 | ||
1207 | return 0; | 1209 | return 0; |
1208 | } | 1210 | } |
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 97687d335903..d7221c4a5dcf 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c | |||
@@ -686,7 +686,7 @@ static int catc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
686 | 686 | ||
687 | cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_TP; | 687 | cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_TP; |
688 | cmd->advertising = ADVERTISED_10baseT_Half | ADVERTISED_TP; | 688 | cmd->advertising = ADVERTISED_10baseT_Half | ADVERTISED_TP; |
689 | cmd->speed = SPEED_10; | 689 | ethtool_cmd_speed_set(cmd, SPEED_10); |
690 | cmd->duplex = DUPLEX_HALF; | 690 | cmd->duplex = DUPLEX_HALF; |
691 | cmd->port = PORT_TP; | 691 | cmd->port = PORT_TP; |
692 | cmd->phy_address = 0; | 692 | cmd->phy_address = 0; |
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 5002f5be47be..1d93133e9b74 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c | |||
@@ -599,13 +599,13 @@ static void dm9601_status(struct usbnet *dev, struct urb *urb) | |||
599 | 599 | ||
600 | static int dm9601_link_reset(struct usbnet *dev) | 600 | static int dm9601_link_reset(struct usbnet *dev) |
601 | { | 601 | { |
602 | struct ethtool_cmd ecmd; | 602 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; |
603 | 603 | ||
604 | mii_check_media(&dev->mii, 1, 1); | 604 | mii_check_media(&dev->mii, 1, 1); |
605 | mii_ethtool_gset(&dev->mii, &ecmd); | 605 | mii_ethtool_gset(&dev->mii, &ecmd); |
606 | 606 | ||
607 | netdev_dbg(dev->net, "link_reset() speed: %d duplex: %d\n", | 607 | netdev_dbg(dev->net, "link_reset() speed: %u duplex: %d\n", |
608 | ecmd.speed, ecmd.duplex); | 608 | ethtool_cmd_speed(&ecmd), ecmd.duplex); |
609 | 609 | ||
610 | return 0; | 610 | return 0; |
611 | } | 611 | } |
diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c index 823c53751307..217aec8a768f 100644 --- a/drivers/net/usb/plusb.c +++ b/drivers/net/usb/plusb.c | |||
@@ -45,6 +45,14 @@ | |||
45 | * seems to get wedged under load. Prolific docs are weak, and | 45 | * seems to get wedged under load. Prolific docs are weak, and |
46 | * don't identify differences between PL2301 and PL2302, much less | 46 | * don't identify differences between PL2301 and PL2302, much less |
47 | * anything to explain the different PL2302 versions observed. | 47 | * anything to explain the different PL2302 versions observed. |
48 | * | ||
49 | * NOTE: pl2501 has several modes, including pl2301 and pl2302 | ||
50 | * compatibility. Some docs suggest the difference between 2301 | ||
51 | * and 2302 is only to make MS-Windows use a different driver... | ||
52 | * | ||
53 | * pl25a1 glue based on patch from Tony Gibbs. Prolific "docs" on | ||
54 | * this chip are as usual incomplete about what control messages | ||
55 | * are supported. | ||
48 | */ | 56 | */ |
49 | 57 | ||
50 | /* | 58 | /* |
@@ -86,16 +94,20 @@ pl_set_QuickLink_features(struct usbnet *dev, int val) | |||
86 | 94 | ||
87 | static int pl_reset(struct usbnet *dev) | 95 | static int pl_reset(struct usbnet *dev) |
88 | { | 96 | { |
97 | int status; | ||
98 | |||
89 | /* some units seem to need this reset, others reject it utterly. | 99 | /* some units seem to need this reset, others reject it utterly. |
90 | * FIXME be more like "naplink" or windows drivers. | 100 | * FIXME be more like "naplink" or windows drivers. |
91 | */ | 101 | */ |
92 | (void) pl_set_QuickLink_features(dev, | 102 | status = pl_set_QuickLink_features(dev, |
93 | PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E); | 103 | PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E); |
104 | if (status != 0 && netif_msg_probe(dev)) | ||
105 | netif_dbg(dev, link, dev->net, "pl_reset --> %d\n", status); | ||
94 | return 0; | 106 | return 0; |
95 | } | 107 | } |
96 | 108 | ||
97 | static const struct driver_info prolific_info = { | 109 | static const struct driver_info prolific_info = { |
98 | .description = "Prolific PL-2301/PL-2302", | 110 | .description = "Prolific PL-2301/PL-2302/PL-25A1", |
99 | .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT, | 111 | .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT, |
100 | /* some PL-2302 versions seem to fail usb_set_interface() */ | 112 | /* some PL-2302 versions seem to fail usb_set_interface() */ |
101 | .reset = pl_reset, | 113 | .reset = pl_reset, |
@@ -111,6 +123,7 @@ static const struct driver_info prolific_info = { | |||
111 | 123 | ||
112 | static const struct usb_device_id products [] = { | 124 | static const struct usb_device_id products [] = { |
113 | 125 | ||
126 | /* full speed cables */ | ||
114 | { | 127 | { |
115 | USB_DEVICE(0x067b, 0x0000), // PL-2301 | 128 | USB_DEVICE(0x067b, 0x0000), // PL-2301 |
116 | .driver_info = (unsigned long) &prolific_info, | 129 | .driver_info = (unsigned long) &prolific_info, |
@@ -119,6 +132,15 @@ static const struct usb_device_id products [] = { | |||
119 | .driver_info = (unsigned long) &prolific_info, | 132 | .driver_info = (unsigned long) &prolific_info, |
120 | }, | 133 | }, |
121 | 134 | ||
135 | /* high speed cables */ | ||
136 | { | ||
137 | USB_DEVICE(0x067b, 0x25a1), /* PL-25A1, no eeprom */ | ||
138 | .driver_info = (unsigned long) &prolific_info, | ||
139 | }, { | ||
140 | USB_DEVICE(0x050d, 0x258a), /* Belkin F5U258/F5U279 (PL-25A1) */ | ||
141 | .driver_info = (unsigned long) &prolific_info, | ||
142 | }, | ||
143 | |||
122 | { }, // END | 144 | { }, // END |
123 | }; | 145 | }; |
124 | MODULE_DEVICE_TABLE(usb, products); | 146 | MODULE_DEVICE_TABLE(usb, products); |
@@ -134,16 +156,16 @@ static struct usb_driver plusb_driver = { | |||
134 | 156 | ||
135 | static int __init plusb_init(void) | 157 | static int __init plusb_init(void) |
136 | { | 158 | { |
137 | return usb_register(&plusb_driver); | 159 | return usb_register(&plusb_driver); |
138 | } | 160 | } |
139 | module_init(plusb_init); | 161 | module_init(plusb_init); |
140 | 162 | ||
141 | static void __exit plusb_exit(void) | 163 | static void __exit plusb_exit(void) |
142 | { | 164 | { |
143 | usb_deregister(&plusb_driver); | 165 | usb_deregister(&plusb_driver); |
144 | } | 166 | } |
145 | module_exit(plusb_exit); | 167 | module_exit(plusb_exit); |
146 | 168 | ||
147 | MODULE_AUTHOR("David Brownell"); | 169 | MODULE_AUTHOR("David Brownell"); |
148 | MODULE_DESCRIPTION("Prolific PL-2301/2302 USB Host to Host Link Driver"); | 170 | MODULE_DESCRIPTION("Prolific PL-2301/2302/25A1 USB Host to Host Link Driver"); |
149 | MODULE_LICENSE("GPL"); | 171 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 5994a25c56ac..255d6a424a6b 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c | |||
@@ -104,8 +104,10 @@ static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg, | |||
104 | int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) | 104 | int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) |
105 | { | 105 | { |
106 | struct cdc_state *info = (void *) &dev->data; | 106 | struct cdc_state *info = (void *) &dev->data; |
107 | struct usb_cdc_notification notification; | ||
107 | int master_ifnum; | 108 | int master_ifnum; |
108 | int retval; | 109 | int retval; |
110 | int partial; | ||
109 | unsigned count; | 111 | unsigned count; |
110 | __le32 rsp; | 112 | __le32 rsp; |
111 | u32 xid = 0, msg_len, request_id; | 113 | u32 xid = 0, msg_len, request_id; |
@@ -133,13 +135,20 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) | |||
133 | if (unlikely(retval < 0 || xid == 0)) | 135 | if (unlikely(retval < 0 || xid == 0)) |
134 | return retval; | 136 | return retval; |
135 | 137 | ||
136 | // FIXME Seems like some devices discard responses when | 138 | /* Some devices don't respond on the control channel until |
137 | // we time out and cancel our "get response" requests... | 139 | * polled on the status channel, so do that first. */ |
138 | // so, this is fragile. Probably need to poll for status. | 140 | if (dev->driver_info->data & RNDIS_DRIVER_DATA_POLL_STATUS) { |
141 | retval = usb_interrupt_msg( | ||
142 | dev->udev, | ||
143 | usb_rcvintpipe(dev->udev, | ||
144 | dev->status->desc.bEndpointAddress), | ||
145 | ¬ification, sizeof(notification), &partial, | ||
146 | RNDIS_CONTROL_TIMEOUT_MS); | ||
147 | if (unlikely(retval < 0)) | ||
148 | return retval; | ||
149 | } | ||
139 | 150 | ||
140 | /* ignore status endpoint, just poll the control channel; | 151 | /* Poll the control channel; the request probably completed immediately */ |
141 | * the request probably completed immediately | ||
142 | */ | ||
143 | rsp = buf->msg_type | RNDIS_MSG_COMPLETION; | 152 | rsp = buf->msg_type | RNDIS_MSG_COMPLETION; |
144 | for (count = 0; count < 10; count++) { | 153 | for (count = 0; count < 10; count++) { |
145 | memset(buf, 0, CONTROL_BUFFER_SIZE); | 154 | memset(buf, 0, CONTROL_BUFFER_SIZE); |
@@ -581,17 +590,33 @@ static const struct driver_info rndis_info = { | |||
581 | .tx_fixup = rndis_tx_fixup, | 590 | .tx_fixup = rndis_tx_fixup, |
582 | }; | 591 | }; |
583 | 592 | ||
593 | static const struct driver_info rndis_poll_status_info = { | ||
594 | .description = "RNDIS device (poll status before control)", | ||
595 | .flags = FLAG_ETHER | FLAG_POINTTOPOINT | FLAG_FRAMING_RN | FLAG_NO_SETINT, | ||
596 | .data = RNDIS_DRIVER_DATA_POLL_STATUS, | ||
597 | .bind = rndis_bind, | ||
598 | .unbind = rndis_unbind, | ||
599 | .status = rndis_status, | ||
600 | .rx_fixup = rndis_rx_fixup, | ||
601 | .tx_fixup = rndis_tx_fixup, | ||
602 | }; | ||
603 | |||
584 | /*-------------------------------------------------------------------------*/ | 604 | /*-------------------------------------------------------------------------*/ |
585 | 605 | ||
586 | static const struct usb_device_id products [] = { | 606 | static const struct usb_device_id products [] = { |
587 | { | 607 | { |
608 | /* 2Wire HomePortal 1000SW */ | ||
609 | USB_DEVICE_AND_INTERFACE_INFO(0x1630, 0x0042, | ||
610 | USB_CLASS_COMM, 2 /* ACM */, 0x0ff), | ||
611 | .driver_info = (unsigned long) &rndis_poll_status_info, | ||
612 | }, { | ||
588 | /* RNDIS is MSFT's un-official variant of CDC ACM */ | 613 | /* RNDIS is MSFT's un-official variant of CDC ACM */ |
589 | USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff), | 614 | USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff), |
590 | .driver_info = (unsigned long) &rndis_info, | 615 | .driver_info = (unsigned long) &rndis_info, |
591 | }, { | 616 | }, { |
592 | /* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */ | 617 | /* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */ |
593 | USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1), | 618 | USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1), |
594 | .driver_info = (unsigned long) &rndis_info, | 619 | .driver_info = (unsigned long) &rndis_poll_status_info, |
595 | }, { | 620 | }, { |
596 | /* RNDIS for tethering */ | 621 | /* RNDIS for tethering */ |
597 | USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3), | 622 | USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3), |
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index e85c89c6706d..041fb7d43c4f 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c | |||
@@ -843,10 +843,11 @@ static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *e | |||
843 | get_registers(dev, BMCR, 2, &bmcr); | 843 | get_registers(dev, BMCR, 2, &bmcr); |
844 | get_registers(dev, ANLP, 2, &lpa); | 844 | get_registers(dev, ANLP, 2, &lpa); |
845 | if (bmcr & BMCR_ANENABLE) { | 845 | if (bmcr & BMCR_ANENABLE) { |
846 | u32 speed = ((lpa & (LPA_100HALF | LPA_100FULL)) ? | ||
847 | SPEED_100 : SPEED_10); | ||
848 | ethtool_cmd_speed_set(ecmd, speed); | ||
846 | ecmd->autoneg = AUTONEG_ENABLE; | 849 | ecmd->autoneg = AUTONEG_ENABLE; |
847 | ecmd->speed = (lpa & (LPA_100HALF | LPA_100FULL)) ? | 850 | if (speed == SPEED_100) |
848 | SPEED_100 : SPEED_10; | ||
849 | if (ecmd->speed == SPEED_100) | ||
850 | ecmd->duplex = (lpa & LPA_100FULL) ? | 851 | ecmd->duplex = (lpa & LPA_100FULL) ? |
851 | DUPLEX_FULL : DUPLEX_HALF; | 852 | DUPLEX_FULL : DUPLEX_HALF; |
852 | else | 853 | else |
@@ -854,8 +855,8 @@ static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *e | |||
854 | DUPLEX_FULL : DUPLEX_HALF; | 855 | DUPLEX_FULL : DUPLEX_HALF; |
855 | } else { | 856 | } else { |
856 | ecmd->autoneg = AUTONEG_DISABLE; | 857 | ecmd->autoneg = AUTONEG_DISABLE; |
857 | ecmd->speed = (bmcr & BMCR_SPEED100) ? | 858 | ethtool_cmd_speed_set(ecmd, ((bmcr & BMCR_SPEED100) ? |
858 | SPEED_100 : SPEED_10; | 859 | SPEED_100 : SPEED_10)); |
859 | ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? | 860 | ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? |
860 | DUPLEX_FULL : DUPLEX_HALF; | 861 | DUPLEX_FULL : DUPLEX_HALF; |
861 | } | 862 | } |
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 753ee6eb7edd..15b3d6888ae9 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c | |||
@@ -65,7 +65,6 @@ struct smsc75xx_priv { | |||
65 | struct usbnet *dev; | 65 | struct usbnet *dev; |
66 | u32 rfe_ctl; | 66 | u32 rfe_ctl; |
67 | u32 multicast_hash_table[DP_SEL_VHF_HASH_LEN]; | 67 | u32 multicast_hash_table[DP_SEL_VHF_HASH_LEN]; |
68 | bool use_rx_csum; | ||
69 | struct mutex dataport_mutex; | 68 | struct mutex dataport_mutex; |
70 | spinlock_t rfe_ctl_lock; | 69 | spinlock_t rfe_ctl_lock; |
71 | struct work_struct set_multicast; | 70 | struct work_struct set_multicast; |
@@ -504,7 +503,7 @@ static int smsc75xx_update_flowcontrol(struct usbnet *dev, u8 duplex, | |||
504 | static int smsc75xx_link_reset(struct usbnet *dev) | 503 | static int smsc75xx_link_reset(struct usbnet *dev) |
505 | { | 504 | { |
506 | struct mii_if_info *mii = &dev->mii; | 505 | struct mii_if_info *mii = &dev->mii; |
507 | struct ethtool_cmd ecmd; | 506 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; |
508 | u16 lcladv, rmtadv; | 507 | u16 lcladv, rmtadv; |
509 | int ret; | 508 | int ret; |
510 | 509 | ||
@@ -520,8 +519,9 @@ static int smsc75xx_link_reset(struct usbnet *dev) | |||
520 | lcladv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); | 519 | lcladv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); |
521 | rmtadv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_LPA); | 520 | rmtadv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_LPA); |
522 | 521 | ||
523 | netif_dbg(dev, link, dev->net, "speed: %d duplex: %d lcladv: %04x" | 522 | netif_dbg(dev, link, dev->net, "speed: %u duplex: %d lcladv: %04x" |
524 | " rmtadv: %04x", ecmd.speed, ecmd.duplex, lcladv, rmtadv); | 523 | " rmtadv: %04x", ethtool_cmd_speed(&ecmd), |
524 | ecmd.duplex, lcladv, rmtadv); | ||
525 | 525 | ||
526 | return smsc75xx_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv); | 526 | return smsc75xx_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv); |
527 | } | 527 | } |
@@ -548,28 +548,6 @@ static void smsc75xx_status(struct usbnet *dev, struct urb *urb) | |||
548 | "unexpected interrupt, intdata=0x%08X", intdata); | 548 | "unexpected interrupt, intdata=0x%08X", intdata); |
549 | } | 549 | } |
550 | 550 | ||
551 | /* Enable or disable Rx checksum offload engine */ | ||
552 | static int smsc75xx_set_rx_csum_offload(struct usbnet *dev) | ||
553 | { | ||
554 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); | ||
555 | unsigned long flags; | ||
556 | int ret; | ||
557 | |||
558 | spin_lock_irqsave(&pdata->rfe_ctl_lock, flags); | ||
559 | |||
560 | if (pdata->use_rx_csum) | ||
561 | pdata->rfe_ctl |= RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM; | ||
562 | else | ||
563 | pdata->rfe_ctl &= ~(RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM); | ||
564 | |||
565 | spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags); | ||
566 | |||
567 | ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); | ||
568 | check_warn_return(ret, "Error writing RFE_CTL"); | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | static int smsc75xx_ethtool_get_eeprom_len(struct net_device *net) | 551 | static int smsc75xx_ethtool_get_eeprom_len(struct net_device *net) |
574 | { | 552 | { |
575 | return MAX_EEPROM_SIZE; | 553 | return MAX_EEPROM_SIZE; |
@@ -599,34 +577,6 @@ static int smsc75xx_ethtool_set_eeprom(struct net_device *netdev, | |||
599 | return smsc75xx_write_eeprom(dev, ee->offset, ee->len, data); | 577 | return smsc75xx_write_eeprom(dev, ee->offset, ee->len, data); |
600 | } | 578 | } |
601 | 579 | ||
602 | static u32 smsc75xx_ethtool_get_rx_csum(struct net_device *netdev) | ||
603 | { | ||
604 | struct usbnet *dev = netdev_priv(netdev); | ||
605 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); | ||
606 | |||
607 | return pdata->use_rx_csum; | ||
608 | } | ||
609 | |||
610 | static int smsc75xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val) | ||
611 | { | ||
612 | struct usbnet *dev = netdev_priv(netdev); | ||
613 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); | ||
614 | |||
615 | pdata->use_rx_csum = !!val; | ||
616 | |||
617 | return smsc75xx_set_rx_csum_offload(dev); | ||
618 | } | ||
619 | |||
620 | static int smsc75xx_ethtool_set_tso(struct net_device *netdev, u32 data) | ||
621 | { | ||
622 | if (data) | ||
623 | netdev->features |= NETIF_F_TSO | NETIF_F_TSO6; | ||
624 | else | ||
625 | netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static const struct ethtool_ops smsc75xx_ethtool_ops = { | 580 | static const struct ethtool_ops smsc75xx_ethtool_ops = { |
631 | .get_link = usbnet_get_link, | 581 | .get_link = usbnet_get_link, |
632 | .nway_reset = usbnet_nway_reset, | 582 | .nway_reset = usbnet_nway_reset, |
@@ -638,12 +588,6 @@ static const struct ethtool_ops smsc75xx_ethtool_ops = { | |||
638 | .get_eeprom_len = smsc75xx_ethtool_get_eeprom_len, | 588 | .get_eeprom_len = smsc75xx_ethtool_get_eeprom_len, |
639 | .get_eeprom = smsc75xx_ethtool_get_eeprom, | 589 | .get_eeprom = smsc75xx_ethtool_get_eeprom, |
640 | .set_eeprom = smsc75xx_ethtool_set_eeprom, | 590 | .set_eeprom = smsc75xx_ethtool_set_eeprom, |
641 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
642 | .set_tx_csum = ethtool_op_set_tx_hw_csum, | ||
643 | .get_rx_csum = smsc75xx_ethtool_get_rx_csum, | ||
644 | .set_rx_csum = smsc75xx_ethtool_set_rx_csum, | ||
645 | .get_tso = ethtool_op_get_tso, | ||
646 | .set_tso = smsc75xx_ethtool_set_tso, | ||
647 | }; | 591 | }; |
648 | 592 | ||
649 | static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) | 593 | static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) |
@@ -782,6 +726,30 @@ static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu) | |||
782 | return usbnet_change_mtu(netdev, new_mtu); | 726 | return usbnet_change_mtu(netdev, new_mtu); |
783 | } | 727 | } |
784 | 728 | ||
729 | /* Enable or disable Rx checksum offload engine */ | ||
730 | static int smsc75xx_set_features(struct net_device *netdev, u32 features) | ||
731 | { | ||
732 | struct usbnet *dev = netdev_priv(netdev); | ||
733 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); | ||
734 | unsigned long flags; | ||
735 | int ret; | ||
736 | |||
737 | spin_lock_irqsave(&pdata->rfe_ctl_lock, flags); | ||
738 | |||
739 | if (features & NETIF_F_RXCSUM) | ||
740 | pdata->rfe_ctl |= RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM; | ||
741 | else | ||
742 | pdata->rfe_ctl &= ~(RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM); | ||
743 | |||
744 | spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags); | ||
745 | /* it's racing here! */ | ||
746 | |||
747 | ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); | ||
748 | check_warn_return(ret, "Error writing RFE_CTL"); | ||
749 | |||
750 | return 0; | ||
751 | } | ||
752 | |||
785 | static int smsc75xx_reset(struct usbnet *dev) | 753 | static int smsc75xx_reset(struct usbnet *dev) |
786 | { | 754 | { |
787 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); | 755 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
@@ -960,11 +928,7 @@ static int smsc75xx_reset(struct usbnet *dev) | |||
960 | netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x", pdata->rfe_ctl); | 928 | netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x", pdata->rfe_ctl); |
961 | 929 | ||
962 | /* Enable or disable checksum offload engines */ | 930 | /* Enable or disable checksum offload engines */ |
963 | ethtool_op_set_tx_hw_csum(dev->net, DEFAULT_TX_CSUM_ENABLE); | 931 | smsc75xx_set_features(dev->net, dev->net->features); |
964 | ret = smsc75xx_set_rx_csum_offload(dev); | ||
965 | check_warn_return(ret, "Failed to set rx csum offload: %d", ret); | ||
966 | |||
967 | smsc75xx_ethtool_set_tso(dev->net, DEFAULT_TSO_ENABLE); | ||
968 | 932 | ||
969 | smsc75xx_set_multicast(dev->net); | 933 | smsc75xx_set_multicast(dev->net); |
970 | 934 | ||
@@ -1037,6 +1001,7 @@ static const struct net_device_ops smsc75xx_netdev_ops = { | |||
1037 | .ndo_validate_addr = eth_validate_addr, | 1001 | .ndo_validate_addr = eth_validate_addr, |
1038 | .ndo_do_ioctl = smsc75xx_ioctl, | 1002 | .ndo_do_ioctl = smsc75xx_ioctl, |
1039 | .ndo_set_multicast_list = smsc75xx_set_multicast, | 1003 | .ndo_set_multicast_list = smsc75xx_set_multicast, |
1004 | .ndo_set_features = smsc75xx_set_features, | ||
1040 | }; | 1005 | }; |
1041 | 1006 | ||
1042 | static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) | 1007 | static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) |
@@ -1065,10 +1030,17 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1065 | 1030 | ||
1066 | INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write); | 1031 | INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write); |
1067 | 1032 | ||
1068 | pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE; | 1033 | if (DEFAULT_TX_CSUM_ENABLE) { |
1034 | dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; | ||
1035 | if (DEFAULT_TSO_ENABLE) | ||
1036 | dev->net->features |= NETIF_F_SG | | ||
1037 | NETIF_F_TSO | NETIF_F_TSO6; | ||
1038 | } | ||
1039 | if (DEFAULT_RX_CSUM_ENABLE) | ||
1040 | dev->net->features |= NETIF_F_RXCSUM; | ||
1069 | 1041 | ||
1070 | /* We have to advertise SG otherwise TSO cannot be enabled */ | 1042 | dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | |
1071 | dev->net->features |= NETIF_F_SG; | 1043 | NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_RXCSUM; |
1072 | 1044 | ||
1073 | /* Init all registers */ | 1045 | /* Init all registers */ |
1074 | ret = smsc75xx_reset(dev); | 1046 | ret = smsc75xx_reset(dev); |
@@ -1091,10 +1063,11 @@ static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf) | |||
1091 | } | 1063 | } |
1092 | } | 1064 | } |
1093 | 1065 | ||
1094 | static void smsc75xx_rx_csum_offload(struct sk_buff *skb, u32 rx_cmd_a, | 1066 | static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb, |
1095 | u32 rx_cmd_b) | 1067 | u32 rx_cmd_a, u32 rx_cmd_b) |
1096 | { | 1068 | { |
1097 | if (unlikely(rx_cmd_a & RX_CMD_A_LCSM)) { | 1069 | if (!(dev->net->features & NETIF_F_RXCSUM) || |
1070 | unlikely(rx_cmd_a & RX_CMD_A_LCSM)) { | ||
1098 | skb->ip_summed = CHECKSUM_NONE; | 1071 | skb->ip_summed = CHECKSUM_NONE; |
1099 | } else { | 1072 | } else { |
1100 | skb->csum = ntohs((u16)(rx_cmd_b >> RX_CMD_B_CSUM_SHIFT)); | 1073 | skb->csum = ntohs((u16)(rx_cmd_b >> RX_CMD_B_CSUM_SHIFT)); |
@@ -1104,8 +1077,6 @@ static void smsc75xx_rx_csum_offload(struct sk_buff *skb, u32 rx_cmd_a, | |||
1104 | 1077 | ||
1105 | static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | 1078 | static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) |
1106 | { | 1079 | { |
1107 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); | ||
1108 | |||
1109 | while (skb->len > 0) { | 1080 | while (skb->len > 0) { |
1110 | u32 rx_cmd_a, rx_cmd_b, align_count, size; | 1081 | u32 rx_cmd_a, rx_cmd_b, align_count, size; |
1111 | struct sk_buff *ax_skb; | 1082 | struct sk_buff *ax_skb; |
@@ -1145,11 +1116,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
1145 | 1116 | ||
1146 | /* last frame in this batch */ | 1117 | /* last frame in this batch */ |
1147 | if (skb->len == size) { | 1118 | if (skb->len == size) { |
1148 | if (pdata->use_rx_csum) | 1119 | smsc75xx_rx_csum_offload(dev, skb, rx_cmd_a, |
1149 | smsc75xx_rx_csum_offload(skb, rx_cmd_a, | 1120 | rx_cmd_b); |
1150 | rx_cmd_b); | ||
1151 | else | ||
1152 | skb->ip_summed = CHECKSUM_NONE; | ||
1153 | 1121 | ||
1154 | skb_trim(skb, skb->len - 4); /* remove fcs */ | 1122 | skb_trim(skb, skb->len - 4); /* remove fcs */ |
1155 | skb->truesize = size + sizeof(struct sk_buff); | 1123 | skb->truesize = size + sizeof(struct sk_buff); |
@@ -1167,11 +1135,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
1167 | ax_skb->data = packet; | 1135 | ax_skb->data = packet; |
1168 | skb_set_tail_pointer(ax_skb, size); | 1136 | skb_set_tail_pointer(ax_skb, size); |
1169 | 1137 | ||
1170 | if (pdata->use_rx_csum) | 1138 | smsc75xx_rx_csum_offload(dev, ax_skb, rx_cmd_a, |
1171 | smsc75xx_rx_csum_offload(ax_skb, rx_cmd_a, | 1139 | rx_cmd_b); |
1172 | rx_cmd_b); | ||
1173 | else | ||
1174 | ax_skb->ip_summed = CHECKSUM_NONE; | ||
1175 | 1140 | ||
1176 | skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ | 1141 | skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ |
1177 | ax_skb->truesize = size + sizeof(struct sk_buff); | 1142 | ax_skb->truesize = size + sizeof(struct sk_buff); |
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 48d4efdb4959..f74f3ce71526 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c | |||
@@ -52,8 +52,6 @@ struct smsc95xx_priv { | |||
52 | u32 hash_hi; | 52 | u32 hash_hi; |
53 | u32 hash_lo; | 53 | u32 hash_lo; |
54 | spinlock_t mac_cr_lock; | 54 | spinlock_t mac_cr_lock; |
55 | bool use_tx_csum; | ||
56 | bool use_rx_csum; | ||
57 | }; | 55 | }; |
58 | 56 | ||
59 | struct usb_context { | 57 | struct usb_context { |
@@ -459,7 +457,7 @@ static int smsc95xx_link_reset(struct usbnet *dev) | |||
459 | { | 457 | { |
460 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | 458 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); |
461 | struct mii_if_info *mii = &dev->mii; | 459 | struct mii_if_info *mii = &dev->mii; |
462 | struct ethtool_cmd ecmd; | 460 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; |
463 | unsigned long flags; | 461 | unsigned long flags; |
464 | u16 lcladv, rmtadv; | 462 | u16 lcladv, rmtadv; |
465 | u32 intdata; | 463 | u32 intdata; |
@@ -474,8 +472,9 @@ static int smsc95xx_link_reset(struct usbnet *dev) | |||
474 | lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); | 472 | lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); |
475 | rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA); | 473 | rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA); |
476 | 474 | ||
477 | netif_dbg(dev, link, dev->net, "speed: %d duplex: %d lcladv: %04x rmtadv: %04x\n", | 475 | netif_dbg(dev, link, dev->net, |
478 | ecmd.speed, ecmd.duplex, lcladv, rmtadv); | 476 | "speed: %u duplex: %d lcladv: %04x rmtadv: %04x\n", |
477 | ethtool_cmd_speed(&ecmd), ecmd.duplex, lcladv, rmtadv); | ||
479 | 478 | ||
480 | spin_lock_irqsave(&pdata->mac_cr_lock, flags); | 479 | spin_lock_irqsave(&pdata->mac_cr_lock, flags); |
481 | if (ecmd.duplex != DUPLEX_FULL) { | 480 | if (ecmd.duplex != DUPLEX_FULL) { |
@@ -517,22 +516,24 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb) | |||
517 | } | 516 | } |
518 | 517 | ||
519 | /* Enable or disable Tx & Rx checksum offload engines */ | 518 | /* Enable or disable Tx & Rx checksum offload engines */ |
520 | static int smsc95xx_set_csums(struct usbnet *dev) | 519 | static int smsc95xx_set_features(struct net_device *netdev, u32 features) |
521 | { | 520 | { |
522 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | 521 | struct usbnet *dev = netdev_priv(netdev); |
523 | u32 read_buf; | 522 | u32 read_buf; |
524 | int ret = smsc95xx_read_reg(dev, COE_CR, &read_buf); | 523 | int ret; |
524 | |||
525 | ret = smsc95xx_read_reg(dev, COE_CR, &read_buf); | ||
525 | if (ret < 0) { | 526 | if (ret < 0) { |
526 | netdev_warn(dev->net, "Failed to read COE_CR: %d\n", ret); | 527 | netdev_warn(dev->net, "Failed to read COE_CR: %d\n", ret); |
527 | return ret; | 528 | return ret; |
528 | } | 529 | } |
529 | 530 | ||
530 | if (pdata->use_tx_csum) | 531 | if (features & NETIF_F_HW_CSUM) |
531 | read_buf |= Tx_COE_EN_; | 532 | read_buf |= Tx_COE_EN_; |
532 | else | 533 | else |
533 | read_buf &= ~Tx_COE_EN_; | 534 | read_buf &= ~Tx_COE_EN_; |
534 | 535 | ||
535 | if (pdata->use_rx_csum) | 536 | if (features & NETIF_F_RXCSUM) |
536 | read_buf |= Rx_COE_EN_; | 537 | read_buf |= Rx_COE_EN_; |
537 | else | 538 | else |
538 | read_buf &= ~Rx_COE_EN_; | 539 | read_buf &= ~Rx_COE_EN_; |
@@ -576,43 +577,6 @@ static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev, | |||
576 | return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data); | 577 | return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data); |
577 | } | 578 | } |
578 | 579 | ||
579 | static u32 smsc95xx_ethtool_get_rx_csum(struct net_device *netdev) | ||
580 | { | ||
581 | struct usbnet *dev = netdev_priv(netdev); | ||
582 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
583 | |||
584 | return pdata->use_rx_csum; | ||
585 | } | ||
586 | |||
587 | static int smsc95xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val) | ||
588 | { | ||
589 | struct usbnet *dev = netdev_priv(netdev); | ||
590 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
591 | |||
592 | pdata->use_rx_csum = !!val; | ||
593 | |||
594 | return smsc95xx_set_csums(dev); | ||
595 | } | ||
596 | |||
597 | static u32 smsc95xx_ethtool_get_tx_csum(struct net_device *netdev) | ||
598 | { | ||
599 | struct usbnet *dev = netdev_priv(netdev); | ||
600 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
601 | |||
602 | return pdata->use_tx_csum; | ||
603 | } | ||
604 | |||
605 | static int smsc95xx_ethtool_set_tx_csum(struct net_device *netdev, u32 val) | ||
606 | { | ||
607 | struct usbnet *dev = netdev_priv(netdev); | ||
608 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
609 | |||
610 | pdata->use_tx_csum = !!val; | ||
611 | |||
612 | ethtool_op_set_tx_hw_csum(netdev, pdata->use_tx_csum); | ||
613 | return smsc95xx_set_csums(dev); | ||
614 | } | ||
615 | |||
616 | static const struct ethtool_ops smsc95xx_ethtool_ops = { | 580 | static const struct ethtool_ops smsc95xx_ethtool_ops = { |
617 | .get_link = usbnet_get_link, | 581 | .get_link = usbnet_get_link, |
618 | .nway_reset = usbnet_nway_reset, | 582 | .nway_reset = usbnet_nway_reset, |
@@ -624,10 +588,6 @@ static const struct ethtool_ops smsc95xx_ethtool_ops = { | |||
624 | .get_eeprom_len = smsc95xx_ethtool_get_eeprom_len, | 588 | .get_eeprom_len = smsc95xx_ethtool_get_eeprom_len, |
625 | .get_eeprom = smsc95xx_ethtool_get_eeprom, | 589 | .get_eeprom = smsc95xx_ethtool_get_eeprom, |
626 | .set_eeprom = smsc95xx_ethtool_set_eeprom, | 590 | .set_eeprom = smsc95xx_ethtool_set_eeprom, |
627 | .get_tx_csum = smsc95xx_ethtool_get_tx_csum, | ||
628 | .set_tx_csum = smsc95xx_ethtool_set_tx_csum, | ||
629 | .get_rx_csum = smsc95xx_ethtool_get_rx_csum, | ||
630 | .set_rx_csum = smsc95xx_ethtool_set_rx_csum, | ||
631 | }; | 591 | }; |
632 | 592 | ||
633 | static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) | 593 | static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) |
@@ -755,7 +715,6 @@ static int smsc95xx_phy_initialize(struct usbnet *dev) | |||
755 | static int smsc95xx_reset(struct usbnet *dev) | 715 | static int smsc95xx_reset(struct usbnet *dev) |
756 | { | 716 | { |
757 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | 717 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); |
758 | struct net_device *netdev = dev->net; | ||
759 | u32 read_buf, write_buf, burst_cap; | 718 | u32 read_buf, write_buf, burst_cap; |
760 | int ret = 0, timeout; | 719 | int ret = 0, timeout; |
761 | 720 | ||
@@ -975,12 +934,7 @@ static int smsc95xx_reset(struct usbnet *dev) | |||
975 | } | 934 | } |
976 | 935 | ||
977 | /* Enable or disable checksum offload engines */ | 936 | /* Enable or disable checksum offload engines */ |
978 | ethtool_op_set_tx_hw_csum(netdev, pdata->use_tx_csum); | 937 | smsc95xx_set_features(dev->net, dev->net->features); |
979 | ret = smsc95xx_set_csums(dev); | ||
980 | if (ret < 0) { | ||
981 | netdev_warn(dev->net, "Failed to set csum offload: %d\n", ret); | ||
982 | return ret; | ||
983 | } | ||
984 | 938 | ||
985 | smsc95xx_set_multicast(dev->net); | 939 | smsc95xx_set_multicast(dev->net); |
986 | 940 | ||
@@ -1019,6 +973,7 @@ static const struct net_device_ops smsc95xx_netdev_ops = { | |||
1019 | .ndo_validate_addr = eth_validate_addr, | 973 | .ndo_validate_addr = eth_validate_addr, |
1020 | .ndo_do_ioctl = smsc95xx_ioctl, | 974 | .ndo_do_ioctl = smsc95xx_ioctl, |
1021 | .ndo_set_multicast_list = smsc95xx_set_multicast, | 975 | .ndo_set_multicast_list = smsc95xx_set_multicast, |
976 | .ndo_set_features = smsc95xx_set_features, | ||
1022 | }; | 977 | }; |
1023 | 978 | ||
1024 | static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) | 979 | static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) |
@@ -1045,8 +1000,12 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1045 | 1000 | ||
1046 | spin_lock_init(&pdata->mac_cr_lock); | 1001 | spin_lock_init(&pdata->mac_cr_lock); |
1047 | 1002 | ||
1048 | pdata->use_tx_csum = DEFAULT_TX_CSUM_ENABLE; | 1003 | if (DEFAULT_TX_CSUM_ENABLE) |
1049 | pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE; | 1004 | dev->net->features |= NETIF_F_HW_CSUM; |
1005 | if (DEFAULT_RX_CSUM_ENABLE) | ||
1006 | dev->net->features |= NETIF_F_RXCSUM; | ||
1007 | |||
1008 | dev->net->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM; | ||
1050 | 1009 | ||
1051 | smsc95xx_init_mac_address(dev); | 1010 | smsc95xx_init_mac_address(dev); |
1052 | 1011 | ||
@@ -1056,7 +1015,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1056 | dev->net->netdev_ops = &smsc95xx_netdev_ops; | 1015 | dev->net->netdev_ops = &smsc95xx_netdev_ops; |
1057 | dev->net->ethtool_ops = &smsc95xx_ethtool_ops; | 1016 | dev->net->ethtool_ops = &smsc95xx_ethtool_ops; |
1058 | dev->net->flags |= IFF_MULTICAST; | 1017 | dev->net->flags |= IFF_MULTICAST; |
1059 | dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD; | 1018 | dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM; |
1060 | return 0; | 1019 | return 0; |
1061 | } | 1020 | } |
1062 | 1021 | ||
@@ -1080,8 +1039,6 @@ static void smsc95xx_rx_csum_offload(struct sk_buff *skb) | |||
1080 | 1039 | ||
1081 | static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | 1040 | static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) |
1082 | { | 1041 | { |
1083 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
1084 | |||
1085 | while (skb->len > 0) { | 1042 | while (skb->len > 0) { |
1086 | u32 header, align_count; | 1043 | u32 header, align_count; |
1087 | struct sk_buff *ax_skb; | 1044 | struct sk_buff *ax_skb; |
@@ -1123,7 +1080,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
1123 | 1080 | ||
1124 | /* last frame in this batch */ | 1081 | /* last frame in this batch */ |
1125 | if (skb->len == size) { | 1082 | if (skb->len == size) { |
1126 | if (pdata->use_rx_csum) | 1083 | if (dev->net->features & NETIF_F_RXCSUM) |
1127 | smsc95xx_rx_csum_offload(skb); | 1084 | smsc95xx_rx_csum_offload(skb); |
1128 | skb_trim(skb, skb->len - 4); /* remove fcs */ | 1085 | skb_trim(skb, skb->len - 4); /* remove fcs */ |
1129 | skb->truesize = size + sizeof(struct sk_buff); | 1086 | skb->truesize = size + sizeof(struct sk_buff); |
@@ -1141,7 +1098,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
1141 | ax_skb->data = packet; | 1098 | ax_skb->data = packet; |
1142 | skb_set_tail_pointer(ax_skb, size); | 1099 | skb_set_tail_pointer(ax_skb, size); |
1143 | 1100 | ||
1144 | if (pdata->use_rx_csum) | 1101 | if (dev->net->features & NETIF_F_RXCSUM) |
1145 | smsc95xx_rx_csum_offload(ax_skb); | 1102 | smsc95xx_rx_csum_offload(ax_skb); |
1146 | skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ | 1103 | skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ |
1147 | ax_skb->truesize = size + sizeof(struct sk_buff); | 1104 | ax_skb->truesize = size + sizeof(struct sk_buff); |
@@ -1174,8 +1131,7 @@ static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb) | |||
1174 | static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, | 1131 | static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, |
1175 | struct sk_buff *skb, gfp_t flags) | 1132 | struct sk_buff *skb, gfp_t flags) |
1176 | { | 1133 | { |
1177 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | 1134 | bool csum = skb->ip_summed == CHECKSUM_PARTIAL; |
1178 | bool csum = pdata->use_tx_csum && (skb->ip_summed == CHECKSUM_PARTIAL); | ||
1179 | int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD; | 1135 | int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD; |
1180 | u32 tx_cmd_a, tx_cmd_b; | 1136 | u32 tx_cmd_a, tx_cmd_b; |
1181 | 1137 | ||
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 9ab439d144ed..e6dd24466965 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
@@ -1541,9 +1541,9 @@ EXPORT_SYMBOL_GPL(usbnet_resume); | |||
1541 | 1541 | ||
1542 | static int __init usbnet_init(void) | 1542 | static int __init usbnet_init(void) |
1543 | { | 1543 | { |
1544 | /* compiler should optimize this out */ | 1544 | /* Compiler should optimize this out. */ |
1545 | BUILD_BUG_ON (sizeof (((struct sk_buff *)0)->cb) | 1545 | BUILD_BUG_ON( |
1546 | < sizeof (struct skb_data)); | 1546 | FIELD_SIZEOF(struct sk_buff, cb) < sizeof(struct skb_data)); |
1547 | 1547 | ||
1548 | random_ether_addr(node_id); | 1548 | random_ether_addr(node_id); |
1549 | return 0; | 1549 | return 0; |