aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/smsc95xx.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/usb/smsc95xx.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/usb/smsc95xx.c')
-rw-r--r--drivers/net/usb/smsc95xx.c135
1 files changed, 54 insertions, 81 deletions
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 12a3c88c5282..f74f3ce71526 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -49,9 +49,9 @@
49 49
50struct smsc95xx_priv { 50struct smsc95xx_priv {
51 u32 mac_cr; 51 u32 mac_cr;
52 u32 hash_hi;
53 u32 hash_lo;
52 spinlock_t mac_cr_lock; 54 spinlock_t mac_cr_lock;
53 bool use_tx_csum;
54 bool use_rx_csum;
55}; 55};
56 56
57struct usb_context { 57struct usb_context {
@@ -370,10 +370,11 @@ static void smsc95xx_set_multicast(struct net_device *netdev)
370{ 370{
371 struct usbnet *dev = netdev_priv(netdev); 371 struct usbnet *dev = netdev_priv(netdev);
372 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 372 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
373 u32 hash_hi = 0;
374 u32 hash_lo = 0;
375 unsigned long flags; 373 unsigned long flags;
376 374
375 pdata->hash_hi = 0;
376 pdata->hash_lo = 0;
377
377 spin_lock_irqsave(&pdata->mac_cr_lock, flags); 378 spin_lock_irqsave(&pdata->mac_cr_lock, flags);
378 379
379 if (dev->net->flags & IFF_PROMISC) { 380 if (dev->net->flags & IFF_PROMISC) {
@@ -394,13 +395,13 @@ static void smsc95xx_set_multicast(struct net_device *netdev)
394 u32 bitnum = smsc95xx_hash(ha->addr); 395 u32 bitnum = smsc95xx_hash(ha->addr);
395 u32 mask = 0x01 << (bitnum & 0x1F); 396 u32 mask = 0x01 << (bitnum & 0x1F);
396 if (bitnum & 0x20) 397 if (bitnum & 0x20)
397 hash_hi |= mask; 398 pdata->hash_hi |= mask;
398 else 399 else
399 hash_lo |= mask; 400 pdata->hash_lo |= mask;
400 } 401 }
401 402
402 netif_dbg(dev, drv, dev->net, "HASHH=0x%08X, HASHL=0x%08X\n", 403 netif_dbg(dev, drv, dev->net, "HASHH=0x%08X, HASHL=0x%08X\n",
403 hash_hi, hash_lo); 404 pdata->hash_hi, pdata->hash_lo);
404 } else { 405 } else {
405 netif_dbg(dev, drv, dev->net, "receive own packets only\n"); 406 netif_dbg(dev, drv, dev->net, "receive own packets only\n");
406 pdata->mac_cr &= 407 pdata->mac_cr &=
@@ -410,8 +411,8 @@ static void smsc95xx_set_multicast(struct net_device *netdev)
410 spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); 411 spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
411 412
412 /* Initiate async writes, as we can't wait for completion here */ 413 /* Initiate async writes, as we can't wait for completion here */
413 smsc95xx_write_reg_async(dev, HASHH, &hash_hi); 414 smsc95xx_write_reg_async(dev, HASHH, &pdata->hash_hi);
414 smsc95xx_write_reg_async(dev, HASHL, &hash_lo); 415 smsc95xx_write_reg_async(dev, HASHL, &pdata->hash_lo);
415 smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr); 416 smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr);
416} 417}
417 418
@@ -456,7 +457,7 @@ static int smsc95xx_link_reset(struct usbnet *dev)
456{ 457{
457 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 458 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
458 struct mii_if_info *mii = &dev->mii; 459 struct mii_if_info *mii = &dev->mii;
459 struct ethtool_cmd ecmd; 460 struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
460 unsigned long flags; 461 unsigned long flags;
461 u16 lcladv, rmtadv; 462 u16 lcladv, rmtadv;
462 u32 intdata; 463 u32 intdata;
@@ -471,8 +472,9 @@ static int smsc95xx_link_reset(struct usbnet *dev)
471 lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); 472 lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE);
472 rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA); 473 rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA);
473 474
474 netif_dbg(dev, link, dev->net, "speed: %d duplex: %d lcladv: %04x rmtadv: %04x\n", 475 netif_dbg(dev, link, dev->net,
475 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);
476 478
477 spin_lock_irqsave(&pdata->mac_cr_lock, flags); 479 spin_lock_irqsave(&pdata->mac_cr_lock, flags);
478 if (ecmd.duplex != DUPLEX_FULL) { 480 if (ecmd.duplex != DUPLEX_FULL) {
@@ -514,22 +516,24 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
514} 516}
515 517
516/* Enable or disable Tx & Rx checksum offload engines */ 518/* Enable or disable Tx & Rx checksum offload engines */
517static int smsc95xx_set_csums(struct usbnet *dev) 519static int smsc95xx_set_features(struct net_device *netdev, u32 features)
518{ 520{
519 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 521 struct usbnet *dev = netdev_priv(netdev);
520 u32 read_buf; 522 u32 read_buf;
521 int ret = smsc95xx_read_reg(dev, COE_CR, &read_buf); 523 int ret;
524
525 ret = smsc95xx_read_reg(dev, COE_CR, &read_buf);
522 if (ret < 0) { 526 if (ret < 0) {
523 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);
524 return ret; 528 return ret;
525 } 529 }
526 530
527 if (pdata->use_tx_csum) 531 if (features & NETIF_F_HW_CSUM)
528 read_buf |= Tx_COE_EN_; 532 read_buf |= Tx_COE_EN_;
529 else 533 else
530 read_buf &= ~Tx_COE_EN_; 534 read_buf &= ~Tx_COE_EN_;
531 535
532 if (pdata->use_rx_csum) 536 if (features & NETIF_F_RXCSUM)
533 read_buf |= Rx_COE_EN_; 537 read_buf |= Rx_COE_EN_;
534 else 538 else
535 read_buf &= ~Rx_COE_EN_; 539 read_buf &= ~Rx_COE_EN_;
@@ -573,43 +577,6 @@ static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev,
573 return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data); 577 return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data);
574} 578}
575 579
576static u32 smsc95xx_ethtool_get_rx_csum(struct net_device *netdev)
577{
578 struct usbnet *dev = netdev_priv(netdev);
579 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
580
581 return pdata->use_rx_csum;
582}
583
584static int smsc95xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val)
585{
586 struct usbnet *dev = netdev_priv(netdev);
587 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
588
589 pdata->use_rx_csum = !!val;
590
591 return smsc95xx_set_csums(dev);
592}
593
594static u32 smsc95xx_ethtool_get_tx_csum(struct net_device *netdev)
595{
596 struct usbnet *dev = netdev_priv(netdev);
597 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
598
599 return pdata->use_tx_csum;
600}
601
602static int smsc95xx_ethtool_set_tx_csum(struct net_device *netdev, u32 val)
603{
604 struct usbnet *dev = netdev_priv(netdev);
605 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
606
607 pdata->use_tx_csum = !!val;
608
609 ethtool_op_set_tx_hw_csum(netdev, pdata->use_tx_csum);
610 return smsc95xx_set_csums(dev);
611}
612
613static const struct ethtool_ops smsc95xx_ethtool_ops = { 580static const struct ethtool_ops smsc95xx_ethtool_ops = {
614 .get_link = usbnet_get_link, 581 .get_link = usbnet_get_link,
615 .nway_reset = usbnet_nway_reset, 582 .nway_reset = usbnet_nway_reset,
@@ -621,10 +588,6 @@ static const struct ethtool_ops smsc95xx_ethtool_ops = {
621 .get_eeprom_len = smsc95xx_ethtool_get_eeprom_len, 588 .get_eeprom_len = smsc95xx_ethtool_get_eeprom_len,
622 .get_eeprom = smsc95xx_ethtool_get_eeprom, 589 .get_eeprom = smsc95xx_ethtool_get_eeprom,
623 .set_eeprom = smsc95xx_ethtool_set_eeprom, 590 .set_eeprom = smsc95xx_ethtool_set_eeprom,
624 .get_tx_csum = smsc95xx_ethtool_get_tx_csum,
625 .set_tx_csum = smsc95xx_ethtool_set_tx_csum,
626 .get_rx_csum = smsc95xx_ethtool_get_rx_csum,
627 .set_rx_csum = smsc95xx_ethtool_set_rx_csum,
628}; 591};
629 592
630static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) 593static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
@@ -727,7 +690,7 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
727 msleep(10); 690 msleep(10);
728 bmcr = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR); 691 bmcr = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
729 timeout++; 692 timeout++;
730 } while ((bmcr & MII_BMCR) && (timeout < 100)); 693 } while ((bmcr & BMCR_RESET) && (timeout < 100));
731 694
732 if (timeout >= 100) { 695 if (timeout >= 100) {
733 netdev_warn(dev->net, "timeout on PHY Reset"); 696 netdev_warn(dev->net, "timeout on PHY Reset");
@@ -752,7 +715,6 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
752static int smsc95xx_reset(struct usbnet *dev) 715static int smsc95xx_reset(struct usbnet *dev)
753{ 716{
754 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 717 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
755 struct net_device *netdev = dev->net;
756 u32 read_buf, write_buf, burst_cap; 718 u32 read_buf, write_buf, burst_cap;
757 int ret = 0, timeout; 719 int ret = 0, timeout;
758 720
@@ -805,8 +767,6 @@ static int smsc95xx_reset(struct usbnet *dev)
805 return ret; 767 return ret;
806 } 768 }
807 769
808 smsc95xx_init_mac_address(dev);
809
810 ret = smsc95xx_set_mac_address(dev); 770 ret = smsc95xx_set_mac_address(dev);
811 if (ret < 0) 771 if (ret < 0)
812 return ret; 772 return ret;
@@ -974,12 +934,7 @@ static int smsc95xx_reset(struct usbnet *dev)
974 } 934 }
975 935
976 /* Enable or disable checksum offload engines */ 936 /* Enable or disable checksum offload engines */
977 ethtool_op_set_tx_hw_csum(netdev, pdata->use_tx_csum); 937 smsc95xx_set_features(dev->net, dev->net->features);
978 ret = smsc95xx_set_csums(dev);
979 if (ret < 0) {
980 netdev_warn(dev->net, "Failed to set csum offload: %d\n", ret);
981 return ret;
982 }
983 938
984 smsc95xx_set_multicast(dev->net); 939 smsc95xx_set_multicast(dev->net);
985 940
@@ -1018,6 +973,7 @@ static const struct net_device_ops smsc95xx_netdev_ops = {
1018 .ndo_validate_addr = eth_validate_addr, 973 .ndo_validate_addr = eth_validate_addr,
1019 .ndo_do_ioctl = smsc95xx_ioctl, 974 .ndo_do_ioctl = smsc95xx_ioctl,
1020 .ndo_set_multicast_list = smsc95xx_set_multicast, 975 .ndo_set_multicast_list = smsc95xx_set_multicast,
976 .ndo_set_features = smsc95xx_set_features,
1021}; 977};
1022 978
1023static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) 979static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
@@ -1044,8 +1000,14 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
1044 1000
1045 spin_lock_init(&pdata->mac_cr_lock); 1001 spin_lock_init(&pdata->mac_cr_lock);
1046 1002
1047 pdata->use_tx_csum = DEFAULT_TX_CSUM_ENABLE; 1003 if (DEFAULT_TX_CSUM_ENABLE)
1048 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;
1009
1010 smsc95xx_init_mac_address(dev);
1049 1011
1050 /* Init all registers */ 1012 /* Init all registers */
1051 ret = smsc95xx_reset(dev); 1013 ret = smsc95xx_reset(dev);
@@ -1053,7 +1015,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
1053 dev->net->netdev_ops = &smsc95xx_netdev_ops; 1015 dev->net->netdev_ops = &smsc95xx_netdev_ops;
1054 dev->net->ethtool_ops = &smsc95xx_ethtool_ops; 1016 dev->net->ethtool_ops = &smsc95xx_ethtool_ops;
1055 dev->net->flags |= IFF_MULTICAST; 1017 dev->net->flags |= IFF_MULTICAST;
1056 dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD; 1018 dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM;
1057 return 0; 1019 return 0;
1058} 1020}
1059 1021
@@ -1077,8 +1039,6 @@ static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
1077 1039
1078static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 1040static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
1079{ 1041{
1080 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
1081
1082 while (skb->len > 0) { 1042 while (skb->len > 0) {
1083 u32 header, align_count; 1043 u32 header, align_count;
1084 struct sk_buff *ax_skb; 1044 struct sk_buff *ax_skb;
@@ -1120,7 +1080,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
1120 1080
1121 /* last frame in this batch */ 1081 /* last frame in this batch */
1122 if (skb->len == size) { 1082 if (skb->len == size) {
1123 if (pdata->use_rx_csum) 1083 if (dev->net->features & NETIF_F_RXCSUM)
1124 smsc95xx_rx_csum_offload(skb); 1084 smsc95xx_rx_csum_offload(skb);
1125 skb_trim(skb, skb->len - 4); /* remove fcs */ 1085 skb_trim(skb, skb->len - 4); /* remove fcs */
1126 skb->truesize = size + sizeof(struct sk_buff); 1086 skb->truesize = size + sizeof(struct sk_buff);
@@ -1138,7 +1098,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
1138 ax_skb->data = packet; 1098 ax_skb->data = packet;
1139 skb_set_tail_pointer(ax_skb, size); 1099 skb_set_tail_pointer(ax_skb, size);
1140 1100
1141 if (pdata->use_rx_csum) 1101 if (dev->net->features & NETIF_F_RXCSUM)
1142 smsc95xx_rx_csum_offload(ax_skb); 1102 smsc95xx_rx_csum_offload(ax_skb);
1143 skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ 1103 skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
1144 ax_skb->truesize = size + sizeof(struct sk_buff); 1104 ax_skb->truesize = size + sizeof(struct sk_buff);
@@ -1163,17 +1123,15 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
1163 1123
1164static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb) 1124static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb)
1165{ 1125{
1166 int len = skb->data - skb->head; 1126 u16 low_16 = (u16)skb_checksum_start_offset(skb);
1167 u16 high_16 = (u16)(skb->csum_offset + skb->csum_start - len); 1127 u16 high_16 = low_16 + skb->csum_offset;
1168 u16 low_16 = (u16)(skb->csum_start - len);
1169 return (high_16 << 16) | low_16; 1128 return (high_16 << 16) | low_16;
1170} 1129}
1171 1130
1172static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, 1131static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
1173 struct sk_buff *skb, gfp_t flags) 1132 struct sk_buff *skb, gfp_t flags)
1174{ 1133{
1175 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 1134 bool csum = skb->ip_summed == CHECKSUM_PARTIAL;
1176 bool csum = pdata->use_tx_csum && (skb->ip_summed == CHECKSUM_PARTIAL);
1177 int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD; 1135 int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
1178 u32 tx_cmd_a, tx_cmd_b; 1136 u32 tx_cmd_a, tx_cmd_b;
1179 1137
@@ -1193,7 +1151,7 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
1193 if (skb->len <= 45) { 1151 if (skb->len <= 45) {
1194 /* workaround - hardware tx checksum does not work 1152 /* workaround - hardware tx checksum does not work
1195 * properly with extremely small packets */ 1153 * properly with extremely small packets */
1196 long csstart = skb->csum_start - skb_headroom(skb); 1154 long csstart = skb_checksum_start_offset(skb);
1197 __wsum calc = csum_partial(skb->data + csstart, 1155 __wsum calc = csum_partial(skb->data + csstart,
1198 skb->len - csstart, 0); 1156 skb->len - csstart, 0);
1199 *((__sum16 *)(skb->data + csstart 1157 *((__sum16 *)(skb->data + csstart
@@ -1311,6 +1269,21 @@ static const struct usb_device_id products[] = {
1311 USB_DEVICE(0x0424, 0x9909), 1269 USB_DEVICE(0x0424, 0x9909),
1312 .driver_info = (unsigned long) &smsc95xx_info, 1270 .driver_info = (unsigned long) &smsc95xx_info,
1313 }, 1271 },
1272 {
1273 /* SMSC LAN9530 USB Ethernet Device */
1274 USB_DEVICE(0x0424, 0x9530),
1275 .driver_info = (unsigned long) &smsc95xx_info,
1276 },
1277 {
1278 /* SMSC LAN9730 USB Ethernet Device */
1279 USB_DEVICE(0x0424, 0x9730),
1280 .driver_info = (unsigned long) &smsc95xx_info,
1281 },
1282 {
1283 /* SMSC LAN89530 USB Ethernet Device */
1284 USB_DEVICE(0x0424, 0x9E08),
1285 .driver_info = (unsigned long) &smsc95xx_info,
1286 },
1314 { }, /* END */ 1287 { }, /* END */
1315}; 1288};
1316MODULE_DEVICE_TABLE(usb, products); 1289MODULE_DEVICE_TABLE(usb, products);