31
31
#include "smsc95xx.h"
32
32
33
33
#define SMSC_CHIPNAME "smsc95xx"
34
- #define SMSC_DRIVER_VERSION "1.0.3 "
34
+ #define SMSC_DRIVER_VERSION "1.0.4 "
35
35
#define HS_USB_PKT_SIZE (512)
36
36
#define FS_USB_PKT_SIZE (64)
37
37
#define DEFAULT_HS_BURST_CAP_SIZE (16 * 1024 + 5 * HS_USB_PKT_SIZE)
40
40
#define MAX_SINGLE_PACKET_SIZE (2048)
41
41
#define LAN95XX_EEPROM_MAGIC (0x9500)
42
42
#define EEPROM_MAC_OFFSET (0x01)
43
+ #define DEFAULT_TX_CSUM_ENABLE (true)
43
44
#define DEFAULT_RX_CSUM_ENABLE (true)
44
45
#define SMSC95XX_INTERNAL_PHY_ID (1)
45
46
#define SMSC95XX_TX_OVERHEAD (8)
47
+ #define SMSC95XX_TX_OVERHEAD_CSUM (12)
46
48
#define FLOW_CTRL_TX (1)
47
49
#define FLOW_CTRL_RX (2)
48
50
49
51
struct smsc95xx_priv {
50
52
u32 mac_cr ;
51
53
spinlock_t mac_cr_lock ;
54
+ bool use_tx_csum ;
52
55
bool use_rx_csum ;
53
56
};
54
57
@@ -556,17 +559,23 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
556
559
devwarn (dev , "unexpected interrupt, intdata=0x%08X" , intdata );
557
560
}
558
561
559
- /* Enable or disable Rx checksum offload engine */
560
- static int smsc95xx_set_rx_csum (struct usbnet * dev , bool enable )
562
+ /* Enable or disable Tx & Rx checksum offload engines */
563
+ static int smsc95xx_set_csums (struct usbnet * dev )
561
564
{
565
+ struct smsc95xx_priv * pdata = (struct smsc95xx_priv * )(dev -> data [0 ]);
562
566
u32 read_buf ;
563
567
int ret = smsc95xx_read_reg (dev , COE_CR , & read_buf );
564
568
if (ret < 0 ) {
565
569
devwarn (dev , "Failed to read COE_CR: %d" , ret );
566
570
return ret ;
567
571
}
568
572
569
- if (enable )
573
+ if (pdata -> use_tx_csum )
574
+ read_buf |= Tx_COE_EN_ ;
575
+ else
576
+ read_buf &= ~Tx_COE_EN_ ;
577
+
578
+ if (pdata -> use_rx_csum )
570
579
read_buf |= Rx_COE_EN_ ;
571
580
else
572
581
read_buf &= ~Rx_COE_EN_ ;
@@ -626,7 +635,26 @@ static int smsc95xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val)
626
635
627
636
pdata -> use_rx_csum = !!val ;
628
637
629
- return smsc95xx_set_rx_csum (dev , pdata -> use_rx_csum );
638
+ return smsc95xx_set_csums (dev );
639
+ }
640
+
641
+ static u32 smsc95xx_ethtool_get_tx_csum (struct net_device * netdev )
642
+ {
643
+ struct usbnet * dev = netdev_priv (netdev );
644
+ struct smsc95xx_priv * pdata = (struct smsc95xx_priv * )(dev -> data [0 ]);
645
+
646
+ return pdata -> use_tx_csum ;
647
+ }
648
+
649
+ static int smsc95xx_ethtool_set_tx_csum (struct net_device * netdev , u32 val )
650
+ {
651
+ struct usbnet * dev = netdev_priv (netdev );
652
+ struct smsc95xx_priv * pdata = (struct smsc95xx_priv * )(dev -> data [0 ]);
653
+
654
+ pdata -> use_tx_csum = !!val ;
655
+
656
+ ethtool_op_set_tx_hw_csum (netdev , pdata -> use_tx_csum );
657
+ return smsc95xx_set_csums (dev );
630
658
}
631
659
632
660
static struct ethtool_ops smsc95xx_ethtool_ops = {
@@ -640,6 +668,8 @@ static struct ethtool_ops smsc95xx_ethtool_ops = {
640
668
.get_eeprom_len = smsc95xx_ethtool_get_eeprom_len ,
641
669
.get_eeprom = smsc95xx_ethtool_get_eeprom ,
642
670
.set_eeprom = smsc95xx_ethtool_set_eeprom ,
671
+ .get_tx_csum = smsc95xx_ethtool_get_tx_csum ,
672
+ .set_tx_csum = smsc95xx_ethtool_set_tx_csum ,
643
673
.get_rx_csum = smsc95xx_ethtool_get_rx_csum ,
644
674
.set_rx_csum = smsc95xx_ethtool_set_rx_csum ,
645
675
};
@@ -757,6 +787,7 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
757
787
static int smsc95xx_reset (struct usbnet * dev )
758
788
{
759
789
struct smsc95xx_priv * pdata = (struct smsc95xx_priv * )(dev -> data [0 ]);
790
+ struct net_device * netdev = dev -> net ;
760
791
u32 read_buf , write_buf , burst_cap ;
761
792
int ret = 0 , timeout ;
762
793
@@ -968,10 +999,11 @@ static int smsc95xx_reset(struct usbnet *dev)
968
999
return ret ;
969
1000
}
970
1001
971
- /* Enable or disable Rx checksum offload engine */
972
- ret = smsc95xx_set_rx_csum (dev , pdata -> use_rx_csum );
1002
+ /* Enable or disable checksum offload engines */
1003
+ ethtool_op_set_tx_hw_csum (netdev , pdata -> use_tx_csum );
1004
+ ret = smsc95xx_set_csums (dev );
973
1005
if (ret < 0 ) {
974
- devwarn (dev , "Failed to set Rx csum offload: %d" , ret );
1006
+ devwarn (dev , "Failed to set csum offload: %d" , ret );
975
1007
return ret ;
976
1008
}
977
1009
@@ -1027,6 +1059,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
1027
1059
1028
1060
spin_lock_init (& pdata -> mac_cr_lock );
1029
1061
1062
+ pdata -> use_tx_csum = DEFAULT_TX_CSUM_ENABLE ;
1030
1063
pdata -> use_rx_csum = DEFAULT_RX_CSUM_ENABLE ;
1031
1064
1032
1065
/* Init all registers */
@@ -1146,22 +1179,44 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
1146
1179
return 1 ;
1147
1180
}
1148
1181
1182
+ static u32 smsc95xx_calc_csum_preamble (struct sk_buff * skb )
1183
+ {
1184
+ int len = skb -> data - skb -> head ;
1185
+ u16 high_16 = (u16 )(skb -> csum_offset + skb -> csum_start - len );
1186
+ u16 low_16 = (u16 )(skb -> csum_start - len );
1187
+ return (high_16 << 16 ) | low_16 ;
1188
+ }
1189
+
1149
1190
static struct sk_buff * smsc95xx_tx_fixup (struct usbnet * dev ,
1150
1191
struct sk_buff * skb , gfp_t flags )
1151
1192
{
1193
+ struct smsc95xx_priv * pdata = (struct smsc95xx_priv * )(dev -> data [0 ]);
1194
+ bool csum = pdata -> use_tx_csum && (skb -> ip_summed == CHECKSUM_PARTIAL );
1195
+ int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD ;
1152
1196
u32 tx_cmd_a , tx_cmd_b ;
1153
1197
1154
- if (skb_headroom (skb ) < SMSC95XX_TX_OVERHEAD ) {
1198
+ /* We do not advertise SG, so skbs should be already linearized */
1199
+ BUG_ON (skb_shinfo (skb )-> nr_frags );
1200
+
1201
+ if (skb_headroom (skb ) < overhead ) {
1155
1202
struct sk_buff * skb2 = skb_copy_expand (skb ,
1156
- SMSC95XX_TX_OVERHEAD , 0 , flags );
1203
+ overhead , 0 , flags );
1157
1204
dev_kfree_skb_any (skb );
1158
1205
skb = skb2 ;
1159
1206
if (!skb )
1160
1207
return NULL ;
1161
1208
}
1162
1209
1210
+ if (csum ) {
1211
+ u32 csum_preamble = smsc95xx_calc_csum_preamble (skb );
1212
+ skb_push (skb , 4 );
1213
+ memcpy (skb -> data , & csum_preamble , 4 );
1214
+ }
1215
+
1163
1216
skb_push (skb , 4 );
1164
1217
tx_cmd_b = (u32 )(skb -> len - 4 );
1218
+ if (csum )
1219
+ tx_cmd_b |= TX_CMD_B_CSUM_ENABLE ;
1165
1220
cpu_to_le32s (& tx_cmd_b );
1166
1221
memcpy (skb -> data , & tx_cmd_b , 4 );
1167
1222
0 commit comments