Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 340540
b: refs/heads/master
c: 1570838
h: refs/heads/master
v: v3
  • Loading branch information
David S. Miller committed Oct 31, 2012
1 parent 42ac944 commit 1c13b3d
Show file tree
Hide file tree
Showing 16 changed files with 462 additions and 90 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0aca86cd92282359d2f7202804bd92e7d092c04e
refs/heads/master: 157083811c933fc223a3193d319c7ac805f30bb7
59 changes: 56 additions & 3 deletions trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <linux/ethtool.h>
#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/if_bridge.h>
#include <linux/prefetch.h>
#include <scsi/fc/fc_fcoe.h>

Expand Down Expand Up @@ -3224,7 +3225,6 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset ^ 1), reg_offset - 1);
IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (~0) << vf_shift);
IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset ^ 1), reg_offset - 1);
IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);

/* Map PF MAC address in RAR Entry 0 to first pool following VFs */
hw->mac.ops.set_vmdq(hw, 0, VMDQ_P(0));
Expand All @@ -3247,8 +3247,6 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)

IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);

/* enable Tx loopback for VF/PF communication */
IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);

/* Enable MAC Anti-Spoofing */
hw->mac.ops.set_mac_anti_spoofing(hw, (adapter->num_vfs != 0),
Expand Down Expand Up @@ -7025,6 +7023,59 @@ static int ixgbe_ndo_fdb_dump(struct sk_buff *skb,
return idx;
}

static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
struct nlmsghdr *nlh)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct nlattr *attr, *br_spec;
int rem;

if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
return -EOPNOTSUPP;

br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);

nla_for_each_nested(attr, br_spec, rem) {
__u16 mode;
u32 reg = 0;

if (nla_type(attr) != IFLA_BRIDGE_MODE)
continue;

mode = nla_get_u16(attr);
if (mode == BRIDGE_MODE_VEPA)
reg = 0;
else if (mode == BRIDGE_MODE_VEB)
reg = IXGBE_PFDTXGSWC_VT_LBEN;
else
return -EINVAL;

IXGBE_WRITE_REG(&adapter->hw, IXGBE_PFDTXGSWC, reg);

e_info(drv, "enabling bridge mode: %s\n",
mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB");
}

return 0;
}

static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
u16 mode;

if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
return 0;

if (IXGBE_READ_REG(&adapter->hw, IXGBE_PFDTXGSWC) & 1)
mode = BRIDGE_MODE_VEB;
else
mode = BRIDGE_MODE_VEPA;

return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode);
}

static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbe_open,
.ndo_stop = ixgbe_close,
Expand Down Expand Up @@ -7064,6 +7115,8 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_fdb_add = ixgbe_ndo_fdb_add,
.ndo_fdb_del = ixgbe_ndo_fdb_del,
.ndo_fdb_dump = ixgbe_ndo_fdb_dump,
.ndo_bridge_setlink = ixgbe_ndo_bridge_setlink,
.ndo_bridge_getlink = ixgbe_ndo_bridge_getlink,
};

/**
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
}
}

/* Initialize default switching mode VEB */
IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);

/* If call to enable VFs succeeded then allocate memory
* for per VF control structures.
*/
Expand Down
10 changes: 10 additions & 0 deletions trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,16 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
}
skb->protocol = eth_type_trans(skb, rx_ring->netdev);

/* Workaround hardware that can't do proper VEPA multicast
* source pruning.
*/
if ((skb->pkt_type & (PACKET_BROADCAST | PACKET_MULTICAST)) &&
!(compare_ether_addr(adapter->netdev->dev_addr,
eth_hdr(skb)->h_source))) {
dev_kfree_skb_irq(skb);
goto next_desc;
}

ixgbevf_receive_skb(q_vector, skb, staterr, rx_desc);

next_desc:
Expand Down
16 changes: 1 addition & 15 deletions trunk/drivers/net/ethernet/qlogic/qla3xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1920,7 +1920,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
{
struct ql_tx_buf_cb *tx_cb;
int i;
int retval = 0;

if (mac_rsp->flags & OB_MAC_IOCB_RSP_S) {
netdev_warn(qdev->ndev,
Expand All @@ -1935,7 +1934,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
"Frame too short to be legal, frame not sent\n");

qdev->ndev->stats.tx_errors++;
retval = -EIO;
goto frame_not_sent;
}

Expand All @@ -1944,7 +1942,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
mac_rsp->transaction_id);

qdev->ndev->stats.tx_errors++;
retval = -EIO;
goto invalid_seg_count;
}

Expand Down Expand Up @@ -3953,15 +3950,4 @@ static struct pci_driver ql3xxx_driver = {
.remove = __devexit_p(ql3xxx_remove),
};

static int __init ql3xxx_init_module(void)
{
return pci_register_driver(&ql3xxx_driver);
}

static void __exit ql3xxx_exit(void)
{
pci_unregister_driver(&ql3xxx_driver);
}

module_init(ql3xxx_init_module);
module_exit(ql3xxx_exit);
module_pci_driver(ql3xxx_driver);
2 changes: 2 additions & 0 deletions trunk/drivers/net/usb/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ config USB_NET_SMSC75XX
config USB_NET_SMSC95XX
tristate "SMSC LAN95XX based USB 2.0 10/100 ethernet devices"
depends on USB_USBNET
select BITREVERSE
select CRC16
select CRC32
help
This option adds support for SMSC LAN95XX based USB 2.0
Expand Down
127 changes: 121 additions & 6 deletions trunk/drivers/net/usb/smsc95xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/bitrev.h>
#include <linux/crc16.h>
#include <linux/crc32.h>
#include <linux/usb/usbnet.h>
#include <linux/slab.h>
Expand All @@ -46,7 +48,8 @@
#define SMSC95XX_INTERNAL_PHY_ID (1)
#define SMSC95XX_TX_OVERHEAD (8)
#define SMSC95XX_TX_OVERHEAD_CSUM (12)
#define SUPPORTED_WAKE (WAKE_MAGIC)
#define SUPPORTED_WAKE (WAKE_UCAST | WAKE_BCAST | \
WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)

#define check_warn(ret, fmt, args...) \
({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
Expand All @@ -63,6 +66,7 @@ struct smsc95xx_priv {
u32 hash_lo;
u32 wolopts;
spinlock_t mac_cr_lock;
int wuff_filter_count;
};

static bool turbo_mode = true;
Expand Down Expand Up @@ -956,6 +960,7 @@ static const struct net_device_ops smsc95xx_netdev_ops = {
static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
{
struct smsc95xx_priv *pdata = NULL;
u32 val;
int ret;

printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
Expand Down Expand Up @@ -986,6 +991,15 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
/* Init all registers */
ret = smsc95xx_reset(dev);

/* detect device revision as different features may be available */
ret = smsc95xx_read_reg(dev, ID_REV, &val);
check_warn_return(ret, "Failed to read ID_REV: %d\n", ret);
val >>= 16;
if ((val == ID_REV_CHIP_ID_9500A_) || (val == ID_REV_CHIP_ID_9512_))
pdata->wuff_filter_count = LAN9500A_WUFF_NUM;
else
pdata->wuff_filter_count = LAN9500_WUFF_NUM;

dev->net->netdev_ops = &smsc95xx_netdev_ops;
dev->net->ethtool_ops = &smsc95xx_ethtool_ops;
dev->net->flags |= IFF_MULTICAST;
Expand All @@ -1005,6 +1019,11 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
}
}

static u16 smsc_crc(const u8 *buffer, size_t len, int filter)
{
return bitrev16(crc16(0xFFFF, buffer, len)) << ((filter % 2) * 16);
}

static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
Expand Down Expand Up @@ -1049,6 +1068,94 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
return 0;
}

if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
u32 *filter_mask = kzalloc(32, GFP_KERNEL);
u32 *command = kzalloc(2, GFP_KERNEL);
u32 *offset = kzalloc(2, GFP_KERNEL);
u32 *crc = kzalloc(4, GFP_KERNEL);
int i, filter = 0;

if (pdata->wolopts & WAKE_BCAST) {
const u8 bcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
netdev_info(dev->net, "enabling broadcast detection");
filter_mask[filter * 4] = 0x003F;
filter_mask[filter * 4 + 1] = 0x00;
filter_mask[filter * 4 + 2] = 0x00;
filter_mask[filter * 4 + 3] = 0x00;
command[filter/4] |= 0x05UL << ((filter % 4) * 8);
offset[filter/4] |= 0x00 << ((filter % 4) * 8);
crc[filter/2] |= smsc_crc(bcast, 6, filter);
filter++;
}

if (pdata->wolopts & WAKE_MCAST) {
const u8 mcast[] = {0x01, 0x00, 0x5E};
netdev_info(dev->net, "enabling multicast detection");
filter_mask[filter * 4] = 0x0007;
filter_mask[filter * 4 + 1] = 0x00;
filter_mask[filter * 4 + 2] = 0x00;
filter_mask[filter * 4 + 3] = 0x00;
command[filter/4] |= 0x09UL << ((filter % 4) * 8);
offset[filter/4] |= 0x00 << ((filter % 4) * 8);
crc[filter/2] |= smsc_crc(mcast, 3, filter);
filter++;
}

if (pdata->wolopts & WAKE_ARP) {
const u8 arp[] = {0x08, 0x06};
netdev_info(dev->net, "enabling ARP detection");
filter_mask[filter * 4] = 0x0003;
filter_mask[filter * 4 + 1] = 0x00;
filter_mask[filter * 4 + 2] = 0x00;
filter_mask[filter * 4 + 3] = 0x00;
command[filter/4] |= 0x05UL << ((filter % 4) * 8);
offset[filter/4] |= 0x0C << ((filter % 4) * 8);
crc[filter/2] |= smsc_crc(arp, 2, filter);
filter++;
}

if (pdata->wolopts & WAKE_UCAST) {
netdev_info(dev->net, "enabling unicast detection");
filter_mask[filter * 4] = 0x003F;
filter_mask[filter * 4 + 1] = 0x00;
filter_mask[filter * 4 + 2] = 0x00;
filter_mask[filter * 4 + 3] = 0x00;
command[filter/4] |= 0x01UL << ((filter % 4) * 8);
offset[filter/4] |= 0x00 << ((filter % 4) * 8);
crc[filter/2] |= smsc_crc(dev->net->dev_addr, ETH_ALEN, filter);
filter++;
}

for (i = 0; i < (pdata->wuff_filter_count * 4); i++) {
ret = smsc95xx_write_reg(dev, WUFF, filter_mask[i]);
check_warn_return(ret, "Error writing WUFF");
}

for (i = 0; i < (pdata->wuff_filter_count / 4); i++) {
ret = smsc95xx_write_reg(dev, WUFF, command[i]);
check_warn_return(ret, "Error writing WUFF");
}

for (i = 0; i < (pdata->wuff_filter_count / 4); i++) {
ret = smsc95xx_write_reg(dev, WUFF, offset[i]);
check_warn_return(ret, "Error writing WUFF");
}

for (i = 0; i < (pdata->wuff_filter_count / 2); i++) {
ret = smsc95xx_write_reg(dev, WUFF, crc[i]);
check_warn_return(ret, "Error writing WUFF");
}

/* clear any pending pattern match packet status */
ret = smsc95xx_read_reg(dev, WUCSR, &val);
check_warn_return(ret, "Error reading WUCSR");

val |= WUCSR_WUFR_;

ret = smsc95xx_write_reg(dev, WUCSR, val);
check_warn_return(ret, "Error writing WUCSR");
}

if (pdata->wolopts & WAKE_MAGIC) {
/* clear any pending magic packet status */
ret = smsc95xx_read_reg(dev, WUCSR, &val);
Expand All @@ -1060,10 +1167,18 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
check_warn_return(ret, "Error writing WUCSR");
}

/* enable/disable magic packup wake */
/* enable/disable wakeup sources */
ret = smsc95xx_read_reg(dev, WUCSR, &val);
check_warn_return(ret, "Error reading WUCSR");

if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
netdev_info(dev->net, "enabling pattern match wakeup");
val |= WUCSR_WAKE_EN_;
} else {
netdev_info(dev->net, "disabling pattern match wakeup");
val &= ~WUCSR_WAKE_EN_;
}

if (pdata->wolopts & WAKE_MAGIC) {
netdev_info(dev->net, "enabling magic packet wakeup");
val |= WUCSR_MPEN_;
Expand All @@ -1084,7 +1199,7 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
ret = smsc95xx_write_reg(dev, PM_CTRL, val);
check_warn_return(ret, "Error writing PM_CTRL");

/* enable receiver */
/* enable receiver to enable frame reception */
smsc95xx_start_rx_path(dev);

/* some wol options are enabled, so enter SUSPEND0 */
Expand Down Expand Up @@ -1123,14 +1238,14 @@ static int smsc95xx_resume(struct usb_interface *intf)

BUG_ON(!dev);

if (pdata->wolopts & WAKE_MAGIC) {
if (pdata->wolopts) {
smsc95xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);

/* Disable magic packup wake */
/* clear wake-up sources */
ret = smsc95xx_read_reg(dev, WUCSR, &val);
check_warn_return(ret, "Error reading WUCSR");

val &= ~WUCSR_MPEN_;
val &= ~(WUCSR_WAKE_EN_ | WUCSR_MPEN_);

ret = smsc95xx_write_reg(dev, WUCSR, val);
check_warn_return(ret, "Error writing WUCSR");
Expand Down
Loading

0 comments on commit 1c13b3d

Please sign in to comment.