Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 266660
b: refs/heads/master
c: 83c61fa
h: refs/heads/master
v: v3
  • Loading branch information
Greg Rose authored and Jeff Kirsher committed Oct 13, 2011
1 parent 5b464df commit ebc177e
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 10 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: 3ceca749668a52bd795585e0f71c6f0b04814f7b
refs/heads/master: 83c61fa97a7d4ef16506a760f9e52b3144978346
4 changes: 4 additions & 0 deletions trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@
#define MAX_EMULATION_MAC_ADDRS 16
#define IXGBE_MAX_PF_MACVLANS 15
#define VMDQ_P(p) ((p) + adapter->num_vfs)
#define IXGBE_82599_VF_DEVICE_ID 0x10ED
#define IXGBE_X540_VF_DEVICE_ID 0x1515

struct vf_data_storage {
unsigned char vf_mac_addresses[ETH_ALEN];
Expand Down Expand Up @@ -512,6 +514,8 @@ struct ixgbe_adapter {
struct hlist_head fdir_filter_list;
union ixgbe_atr_input fdir_mask;
int fdir_filter_count;
u32 timer_event_accumulator;
u32 vferr_refcount;
};

struct ixgbe_fdir_filter {
Expand Down
172 changes: 171 additions & 1 deletion trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6112,6 +6112,51 @@ static void ixgbe_sfp_link_config_subtask(struct ixgbe_adapter *adapter)
clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state);
}

#ifdef CONFIG_PCI_IOV
static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
{
int vf;
struct ixgbe_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
u32 gpc;
u32 ciaa, ciad;

gpc = IXGBE_READ_REG(hw, IXGBE_TXDGPC);
if (gpc) /* If incrementing then no need for the check below */
return;
/*
* Check to see if a bad DMA write target from an errant or
* malicious VF has caused a PCIe error. If so then we can
* issue a VFLR to the offending VF(s) and then resume without
* requesting a full slot reset.
*/

for (vf = 0; vf < adapter->num_vfs; vf++) {
ciaa = (vf << 16) | 0x80000000;
/* 32 bit read so align, we really want status at offset 6 */
ciaa |= PCI_COMMAND;
IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
ciad = IXGBE_READ_REG(hw, IXGBE_CIAD_82599);
ciaa &= 0x7FFFFFFF;
/* disable debug mode asap after reading data */
IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
/* Get the upper 16 bits which will be the PCI status reg */
ciad >>= 16;
if (ciad & PCI_STATUS_REC_MASTER_ABORT) {
netdev_err(netdev, "VF %d Hung DMA\n", vf);
/* Issue VFLR */
ciaa = (vf << 16) | 0x80000000;
ciaa |= 0xA8;
IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
ciad = 0x00008000; /* VFLR */
IXGBE_WRITE_REG(hw, IXGBE_CIAD_82599, ciad);
ciaa &= 0x7FFFFFFF;
IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
}
}
}

#endif
/**
* ixgbe_service_timer - Timer Call-back
* @data: pointer to adapter cast into an unsigned long
Expand All @@ -6120,17 +6165,49 @@ static void ixgbe_service_timer(unsigned long data)
{
struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
unsigned long next_event_offset;
bool ready = true;

#ifdef CONFIG_PCI_IOV
ready = false;

/*
* don't bother with SR-IOV VF DMA hang check if there are
* no VFs or the link is down
*/
if (!adapter->num_vfs ||
(adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE)) {
ready = true;
goto normal_timer_service;
}

/* If we have VFs allocated then we must check for DMA hangs */
ixgbe_check_for_bad_vf(adapter);
next_event_offset = HZ / 50;
adapter->timer_event_accumulator++;

if (adapter->timer_event_accumulator >= 100) {
ready = true;
adapter->timer_event_accumulator = 0;
}

goto schedule_event;

normal_timer_service:
#endif
/* poll faster when waiting for link */
if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE)
next_event_offset = HZ / 10;
else
next_event_offset = HZ * 2;

#ifdef CONFIG_PCI_IOV
schedule_event:
#endif
/* Reset the timer */
mod_timer(&adapter->service_timer, next_event_offset + jiffies);

ixgbe_service_event_schedule(adapter);
if (ready)
ixgbe_service_event_schedule(adapter);
}

static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter)
Expand Down Expand Up @@ -7717,6 +7794,91 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
struct net_device *netdev = adapter->netdev;

#ifdef CONFIG_PCI_IOV
struct pci_dev *bdev, *vfdev;
u32 dw0, dw1, dw2, dw3;
int vf, pos;
u16 req_id, pf_func;

if (adapter->hw.mac.type == ixgbe_mac_82598EB ||
adapter->num_vfs == 0)
goto skip_bad_vf_detection;

bdev = pdev->bus->self;
while (bdev && (bdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT))
bdev = bdev->bus->self;

if (!bdev)
goto skip_bad_vf_detection;

pos = pci_find_ext_capability(bdev, PCI_EXT_CAP_ID_ERR);
if (!pos)
goto skip_bad_vf_detection;

pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG, &dw0);
pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 4, &dw1);
pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 8, &dw2);
pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 12, &dw3);

req_id = dw1 >> 16;
/* On the 82599 if bit 7 of the requestor ID is set then it's a VF */
if (!(req_id & 0x0080))
goto skip_bad_vf_detection;

pf_func = req_id & 0x01;
if ((pf_func & 1) == (pdev->devfn & 1)) {
unsigned int device_id;

vf = (req_id & 0x7F) >> 1;
e_dev_err("VF %d has caused a PCIe error\n", vf);
e_dev_err("TLP: dw0: %8.8x\tdw1: %8.8x\tdw2: "
"%8.8x\tdw3: %8.8x\n",
dw0, dw1, dw2, dw3);
switch (adapter->hw.mac.type) {
case ixgbe_mac_82599EB:
device_id = IXGBE_82599_VF_DEVICE_ID;
break;
case ixgbe_mac_X540:
device_id = IXGBE_X540_VF_DEVICE_ID;
break;
default:
device_id = 0;
break;
}

/* Find the pci device of the offending VF */
vfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID, device_id, NULL);
while (vfdev) {
if (vfdev->devfn == (req_id & 0xFF))
break;
vfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID,
device_id, vfdev);
}
/*
* There's a slim chance the VF could have been hot plugged,
* so if it is no longer present we don't need to issue the
* VFLR. Just clean up the AER in that case.
*/
if (vfdev) {
e_dev_err("Issuing VFLR to VF %d\n", vf);
pci_write_config_dword(vfdev, 0xA8, 0x00008000);
}

pci_cleanup_aer_uncorrect_error_status(pdev);
}

/*
* Even though the error may have occurred on the other port
* we still need to increment the vf error reference count for
* both ports because the I/O resume function will be called
* for both of them.
*/
adapter->vferr_refcount++;

return PCI_ERS_RESULT_RECOVERED;

skip_bad_vf_detection:
#endif /* CONFIG_PCI_IOV */
netif_device_detach(netdev);

if (state == pci_channel_io_perm_failure)
Expand Down Expand Up @@ -7779,6 +7941,14 @@ static void ixgbe_io_resume(struct pci_dev *pdev)
struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
struct net_device *netdev = adapter->netdev;

#ifdef CONFIG_PCI_IOV
if (adapter->vferr_refcount) {
e_info(drv, "Resuming after VF err\n");
adapter->vferr_refcount--;
return;
}

#endif
if (netif_running(netdev))
ixgbe_up(adapter);

Expand Down
3 changes: 1 addition & 2 deletions trunk/include/linux/inet_diag.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,9 @@ enum {
INET_DIAG_INFO,
INET_DIAG_VEGASINFO,
INET_DIAG_CONG,
INET_DIAG_TOS,
};

#define INET_DIAG_MAX INET_DIAG_TOS
#define INET_DIAG_MAX INET_DIAG_CONG


/* INET_DIAG_MEM */
Expand Down
2 changes: 1 addition & 1 deletion trunk/net/ipv4/cipso_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
doi = doi_def->doi;
doi_type = doi_def->type;

if (doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
goto doi_add_return;
for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) {
switch (doi_def->tags[iter]) {
Expand Down
5 changes: 0 additions & 5 deletions trunk/net/ipv4/inet_diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,6 @@ static int inet_csk_diag_fill(struct sock *sk,
icsk->icsk_ca_ops->name);
}

if ((ext & (1 << (INET_DIAG_TOS - 1))) && (sk->sk_family != AF_INET6))
RTA_PUT_U8(skb, INET_DIAG_TOS, inet->tos);

r->idiag_family = sk->sk_family;
r->idiag_state = sk->sk_state;
r->idiag_timer = 0;
Expand All @@ -133,8 +130,6 @@ static int inet_csk_diag_fill(struct sock *sk,
&np->rcv_saddr);
ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst,
&np->daddr);
if (ext & (1 << (INET_DIAG_TOS - 1)))
RTA_PUT_U8(skb, INET_DIAG_TOS, np->tclass);
}
#endif

Expand Down

0 comments on commit ebc177e

Please sign in to comment.