Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Pull networking fixes from David Miller:
 "Here are some bug fixes that have piled up during ksummit/linuxcon.

   1) Fix endian problems in ibmveth, from Anton Blanchard.

   2) IPV6 routing code does GFP_KERNEL allocation in atomic, fix from
      Benjamin Block.

   3) SCTP association fixes from Daniel Borkmann.

   4) When multiple VLAN headers are present we have to make sure the
      second and subsequent ones are pullable in the SKB otherwise we
      blindly dereference garbage.  From Jiri Benc.

   5) The argument adjustment of the signature of hlist_add_after*()
      introduced a regression in the batman-adv code, fix from Sven
      Eckelmann.

   6) Fix TX hang handling to avoid a panic in i40e, from Anjali Singhai
      Jain.

   7) PTP flag test is inverted in i40e driver, from Jesse Brandeburg.

   8) ATM LEC driver needs to hold RTNL mutex over MTU changes, from
      Chas Williams.

   9) Truncate packets larger then the TPACKET_V3 format configured
      buffers, otherwise we overwrite past the end of said buffers.
      From Eric Dumazet.

  10) Fix endianness bugs in qlcnic firmware handling, from Rajesh
      Borundia and Shahed Shaikh.

  11) CXGB4 sometimes doesn't get all of the TX completion events it
      should resulting in SKBs getting stuck in the TX queue, from
      Hariprasad Shenai.

  12) When the FEC chip's PTP clock is disabled, you can't access the
      register.  Add necessary checks to avoid the resulting hang, from
      Fugang Duan"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (37 commits)
  drivers: isdn: eicon: xdi_msg.h: Fix typo in #ifndef
  net: sctp: fix suboptimal edge-case on non-active active/retrans path selection
  net: sctp: spare unnecessary comparison in sctp_trans_elect_best
  net: ethernet: broadcom: bnx2x: Remove redundant #ifdef
  ibmveth: Fix endian issues with rx_no_buffer statistic
  net: xgene: fix possible NULL dereference in xgene_enet_free_desc_rings()
  openvswitch: fix panic with multiple vlan headers
  net: ipv6: fib: don't sleep inside atomic lock
  net: fec: ptp: avoid register access when ipg clock is disabled
  cxgb4: Free completed tx skbs promptly
  cxgb4: Fix race condition in cleanup
  sctp: not send SCTP_PEER_ADDR_CHANGE notifications with failed probe
  bnx2x: Revert UNDI flushing mechanism
  qlcnic: Fix endianess issue in firmware load from file operation
  qlcnic: Fix endianess issue in FW dump template header
  qlcnic: Fix flash access interface to application
  MAINTAINERS: Add section for MRF24J40 IEEE 802.15.4 radio driver
  macvlan: Allow setting multicast filter on all macvlan types
  packet: handle too big packets for PACKET_V3
  MAINTAINERS: add entry for ec_bhf driver
  ...
This commit is contained in:
Linus Torvalds 2014-08-22 14:33:18 -07:00
commit 433ab34d26
38 changed files with 412 additions and 260 deletions

View File

@ -1843,6 +1843,12 @@ S: Orphan
F: Documentation/filesystems/befs.txt F: Documentation/filesystems/befs.txt
F: fs/befs/ F: fs/befs/
BECKHOFF CX5020 ETHERCAT MASTER DRIVER
M: Dariusz Marcinkiewicz <reksio@newterm.pl>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/ec_bhf.c
BFS FILE SYSTEM BFS FILE SYSTEM
M: "Tigran A. Aivazian" <tigran@aivazian.fsnet.co.uk> M: "Tigran A. Aivazian" <tigran@aivazian.fsnet.co.uk>
S: Maintained S: Maintained
@ -5982,6 +5988,12 @@ T: git git://linuxtv.org/media_tree.git
S: Maintained S: Maintained
F: drivers/media/radio/radio-mr800.c F: drivers/media/radio/radio-mr800.c
MRF24J40 IEEE 802.15.4 RADIO DRIVER
M: Alan Ott <alan@signal11.us>
L: linux-wpan@vger.kernel.org
S: Maintained
F: drivers/net/ieee802154/mrf24j40.c
MSI LAPTOP SUPPORT MSI LAPTOP SUPPORT
M: "Lee, Chun-Yi" <jlee@suse.com> M: "Lee, Chun-Yi" <jlee@suse.com>
L: platform-driver-x86@vger.kernel.org L: platform-driver-x86@vger.kernel.org

View File

@ -1,6 +1,6 @@
/* $Id: xdi_msg.h,v 1.1.2.2 2001/02/16 08:40:36 armin Exp $ */ /* $Id: xdi_msg.h,v 1.1.2.2 2001/02/16 08:40:36 armin Exp $ */
#ifndef __DIVA_XDI_UM_CFG_MESSSGE_H__ #ifndef __DIVA_XDI_UM_CFG_MESSAGE_H__
#define __DIVA_XDI_UM_CFG_MESSAGE_H__ #define __DIVA_XDI_UM_CFG_MESSAGE_H__
/* /*

View File

@ -280,7 +280,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
priv->raminit_ctrlreg = devm_ioremap(&pdev->dev, res->start, priv->raminit_ctrlreg = devm_ioremap(&pdev->dev, res->start,
resource_size(res)); resource_size(res));
if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0) if (!priv->raminit_ctrlreg || priv->instance < 0)
dev_info(&pdev->dev, "control memory is not used for raminit\n"); dev_info(&pdev->dev, "control memory is not used for raminit\n");
else else
priv->raminit = c_can_hw_raminit_ti; priv->raminit = c_can_hw_raminit_ti;

View File

@ -549,6 +549,13 @@ static void do_state(struct net_device *dev,
/* process state changes depending on the new state */ /* process state changes depending on the new state */
switch (new_state) { switch (new_state) {
case CAN_STATE_ERROR_WARNING:
netdev_dbg(dev, "Error Warning\n");
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = (bec.txerr > bec.rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
break;
case CAN_STATE_ERROR_ACTIVE: case CAN_STATE_ERROR_ACTIVE:
netdev_dbg(dev, "Error Active\n"); netdev_dbg(dev, "Error Active\n");
cf->can_id |= CAN_ERR_PROT; cf->can_id |= CAN_ERR_PROT;
@ -852,6 +859,8 @@ static int flexcan_chip_start(struct net_device *dev)
if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE || if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE ||
priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
reg_ctrl |= FLEXCAN_CTRL_ERR_MSK; reg_ctrl |= FLEXCAN_CTRL_ERR_MSK;
else
reg_ctrl &= ~FLEXCAN_CTRL_ERR_MSK;
/* save for later use */ /* save for later use */
priv->reg_ctrl_default = reg_ctrl; priv->reg_ctrl_default = reg_ctrl;

View File

@ -172,6 +172,35 @@ static void set_normal_mode(struct net_device *dev)
netdev_err(dev, "setting SJA1000 into normal mode failed!\n"); netdev_err(dev, "setting SJA1000 into normal mode failed!\n");
} }
/*
* initialize SJA1000 chip:
* - reset chip
* - set output mode
* - set baudrate
* - enable interrupts
* - start operating mode
*/
static void chipset_init(struct net_device *dev)
{
struct sja1000_priv *priv = netdev_priv(dev);
/* set clock divider and output control register */
priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN);
/* set acceptance filter (accept all) */
priv->write_reg(priv, SJA1000_ACCC0, 0x00);
priv->write_reg(priv, SJA1000_ACCC1, 0x00);
priv->write_reg(priv, SJA1000_ACCC2, 0x00);
priv->write_reg(priv, SJA1000_ACCC3, 0x00);
priv->write_reg(priv, SJA1000_ACCM0, 0xFF);
priv->write_reg(priv, SJA1000_ACCM1, 0xFF);
priv->write_reg(priv, SJA1000_ACCM2, 0xFF);
priv->write_reg(priv, SJA1000_ACCM3, 0xFF);
priv->write_reg(priv, SJA1000_OCR, priv->ocr | OCR_MODE_NORMAL);
}
static void sja1000_start(struct net_device *dev) static void sja1000_start(struct net_device *dev)
{ {
struct sja1000_priv *priv = netdev_priv(dev); struct sja1000_priv *priv = netdev_priv(dev);
@ -180,6 +209,10 @@ static void sja1000_start(struct net_device *dev)
if (priv->can.state != CAN_STATE_STOPPED) if (priv->can.state != CAN_STATE_STOPPED)
set_reset_mode(dev); set_reset_mode(dev);
/* Initialize chip if uninitialized at this stage */
if (!(priv->read_reg(priv, SJA1000_CDR) & CDR_PELICAN))
chipset_init(dev);
/* Clear error counters and error code capture */ /* Clear error counters and error code capture */
priv->write_reg(priv, SJA1000_TXERR, 0x0); priv->write_reg(priv, SJA1000_TXERR, 0x0);
priv->write_reg(priv, SJA1000_RXERR, 0x0); priv->write_reg(priv, SJA1000_RXERR, 0x0);
@ -236,35 +269,6 @@ static int sja1000_get_berr_counter(const struct net_device *dev,
return 0; return 0;
} }
/*
* initialize SJA1000 chip:
* - reset chip
* - set output mode
* - set baudrate
* - enable interrupts
* - start operating mode
*/
static void chipset_init(struct net_device *dev)
{
struct sja1000_priv *priv = netdev_priv(dev);
/* set clock divider and output control register */
priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN);
/* set acceptance filter (accept all) */
priv->write_reg(priv, SJA1000_ACCC0, 0x00);
priv->write_reg(priv, SJA1000_ACCC1, 0x00);
priv->write_reg(priv, SJA1000_ACCC2, 0x00);
priv->write_reg(priv, SJA1000_ACCC3, 0x00);
priv->write_reg(priv, SJA1000_ACCM0, 0xFF);
priv->write_reg(priv, SJA1000_ACCM1, 0xFF);
priv->write_reg(priv, SJA1000_ACCM2, 0xFF);
priv->write_reg(priv, SJA1000_ACCM3, 0xFF);
priv->write_reg(priv, SJA1000_OCR, priv->ocr | OCR_MODE_NORMAL);
}
/* /*
* transmit a CAN message * transmit a CAN message
* message layout in the sk_buff should be like this: * message layout in the sk_buff should be like this:

View File

@ -563,15 +563,21 @@ static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
struct xgene_enet_desc_ring *ring; struct xgene_enet_desc_ring *ring;
ring = pdata->tx_ring; ring = pdata->tx_ring;
if (ring && ring->cp_ring && ring->cp_ring->cp_skb) if (ring) {
devm_kfree(dev, ring->cp_ring->cp_skb); if (ring->cp_ring && ring->cp_ring->cp_skb)
xgene_enet_free_desc_ring(ring); devm_kfree(dev, ring->cp_ring->cp_skb);
xgene_enet_free_desc_ring(ring);
}
ring = pdata->rx_ring; ring = pdata->rx_ring;
if (ring && ring->buf_pool && ring->buf_pool->rx_skb) if (ring) {
devm_kfree(dev, ring->buf_pool->rx_skb); if (ring->buf_pool) {
xgene_enet_free_desc_ring(ring->buf_pool); if (ring->buf_pool->rx_skb)
xgene_enet_free_desc_ring(ring); devm_kfree(dev, ring->buf_pool->rx_skb);
xgene_enet_free_desc_ring(ring->buf_pool);
}
xgene_enet_free_desc_ring(ring);
}
} }
static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring( static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(

View File

@ -483,11 +483,7 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
#ifdef BNX2X_STOP_ON_ERROR #ifdef BNX2X_STOP_ON_ERROR
fp->tpa_queue_used |= (1 << queue); fp->tpa_queue_used |= (1 << queue);
#ifdef _ASM_GENERIC_INT_L64_H
DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%lx\n",
#else
DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%llx\n", DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%llx\n",
#endif
fp->tpa_queue_used); fp->tpa_queue_used);
#endif #endif
} }

View File

@ -10052,6 +10052,8 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
} }
#define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4)) #define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4))
#define BNX2X_PREV_UNDI_PROD_ADDR_H(f) (BAR_TSTRORM_INTMEM + \
0x1848 + ((f) << 4))
#define BNX2X_PREV_UNDI_RCQ(val) ((val) & 0xffff) #define BNX2X_PREV_UNDI_RCQ(val) ((val) & 0xffff)
#define BNX2X_PREV_UNDI_BD(val) ((val) >> 16 & 0xffff) #define BNX2X_PREV_UNDI_BD(val) ((val) >> 16 & 0xffff)
#define BNX2X_PREV_UNDI_PROD(rcq, bd) ((bd) << 16 | (rcq)) #define BNX2X_PREV_UNDI_PROD(rcq, bd) ((bd) << 16 | (rcq))
@ -10059,8 +10061,6 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
#define BCM_5710_UNDI_FW_MF_MAJOR (0x07) #define BCM_5710_UNDI_FW_MF_MAJOR (0x07)
#define BCM_5710_UNDI_FW_MF_MINOR (0x08) #define BCM_5710_UNDI_FW_MF_MINOR (0x08)
#define BCM_5710_UNDI_FW_MF_VERS (0x05) #define BCM_5710_UNDI_FW_MF_VERS (0x05)
#define BNX2X_PREV_UNDI_MF_PORT(p) (BAR_TSTRORM_INTMEM + 0x150c + ((p) << 4))
#define BNX2X_PREV_UNDI_MF_FUNC(f) (BAR_TSTRORM_INTMEM + 0x184c + ((f) << 4))
static bool bnx2x_prev_is_after_undi(struct bnx2x *bp) static bool bnx2x_prev_is_after_undi(struct bnx2x *bp)
{ {
@ -10079,72 +10079,25 @@ static bool bnx2x_prev_is_after_undi(struct bnx2x *bp)
return false; return false;
} }
static bool bnx2x_prev_unload_undi_fw_supports_mf(struct bnx2x *bp) static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 inc)
{
u8 major, minor, version;
u32 fw;
/* Must check that FW is loaded */
if (!(REG_RD(bp, MISC_REG_RESET_REG_1) &
MISC_REGISTERS_RESET_REG_1_RST_XSEM)) {
BNX2X_DEV_INFO("XSEM is reset - UNDI MF FW is not loaded\n");
return false;
}
/* Read Currently loaded FW version */
fw = REG_RD(bp, XSEM_REG_PRAM);
major = fw & 0xff;
minor = (fw >> 0x8) & 0xff;
version = (fw >> 0x10) & 0xff;
BNX2X_DEV_INFO("Loaded FW: 0x%08x: Major 0x%02x Minor 0x%02x Version 0x%02x\n",
fw, major, minor, version);
if (major > BCM_5710_UNDI_FW_MF_MAJOR)
return true;
if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
(minor > BCM_5710_UNDI_FW_MF_MINOR))
return true;
if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
(minor == BCM_5710_UNDI_FW_MF_MINOR) &&
(version >= BCM_5710_UNDI_FW_MF_VERS))
return true;
return false;
}
static void bnx2x_prev_unload_undi_mf(struct bnx2x *bp)
{
int i;
/* Due to legacy (FW) code, the first function on each engine has a
* different offset macro from the rest of the functions.
* Setting this for all 8 functions is harmless regardless of whether
* this is actually a multi-function device.
*/
for (i = 0; i < 2; i++)
REG_WR(bp, BNX2X_PREV_UNDI_MF_PORT(i), 1);
for (i = 2; i < 8; i++)
REG_WR(bp, BNX2X_PREV_UNDI_MF_FUNC(i - 2), 1);
BNX2X_DEV_INFO("UNDI FW (MF) set to discard\n");
}
static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, u8 inc)
{ {
u16 rcq, bd; u16 rcq, bd;
u32 tmp_reg = REG_RD(bp, BNX2X_PREV_UNDI_PROD_ADDR(port)); u32 addr, tmp_reg;
if (BP_FUNC(bp) < 2)
addr = BNX2X_PREV_UNDI_PROD_ADDR(BP_PORT(bp));
else
addr = BNX2X_PREV_UNDI_PROD_ADDR_H(BP_FUNC(bp) - 2);
tmp_reg = REG_RD(bp, addr);
rcq = BNX2X_PREV_UNDI_RCQ(tmp_reg) + inc; rcq = BNX2X_PREV_UNDI_RCQ(tmp_reg) + inc;
bd = BNX2X_PREV_UNDI_BD(tmp_reg) + inc; bd = BNX2X_PREV_UNDI_BD(tmp_reg) + inc;
tmp_reg = BNX2X_PREV_UNDI_PROD(rcq, bd); tmp_reg = BNX2X_PREV_UNDI_PROD(rcq, bd);
REG_WR(bp, BNX2X_PREV_UNDI_PROD_ADDR(port), tmp_reg); REG_WR(bp, addr, tmp_reg);
BNX2X_DEV_INFO("UNDI producer [%d] rings bd -> 0x%04x, rcq -> 0x%04x\n", BNX2X_DEV_INFO("UNDI producer [%d/%d][%08x] rings bd -> 0x%04x, rcq -> 0x%04x\n",
port, bd, rcq); BP_PORT(bp), BP_FUNC(bp), addr, bd, rcq);
} }
static int bnx2x_prev_mcp_done(struct bnx2x *bp) static int bnx2x_prev_mcp_done(struct bnx2x *bp)
@ -10383,7 +10336,6 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
/* Reset should be performed after BRB is emptied */ /* Reset should be performed after BRB is emptied */
if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) { if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) {
u32 timer_count = 1000; u32 timer_count = 1000;
bool need_write = true;
/* Close the MAC Rx to prevent BRB from filling up */ /* Close the MAC Rx to prevent BRB from filling up */
bnx2x_prev_unload_close_mac(bp, &mac_vals); bnx2x_prev_unload_close_mac(bp, &mac_vals);
@ -10420,20 +10372,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
else else
timer_count--; timer_count--;
/* New UNDI FW supports MF and contains better /* If UNDI resides in memory, manually increment it */
* cleaning methods - might be redundant but harmless. if (prev_undi)
*/ bnx2x_prev_unload_undi_inc(bp, 1);
if (bnx2x_prev_unload_undi_fw_supports_mf(bp)) {
if (need_write) {
bnx2x_prev_unload_undi_mf(bp);
need_write = false;
}
} else if (prev_undi) {
/* If UNDI resides in memory,
* manually increment it
*/
bnx2x_prev_unload_undi_inc(bp, BP_PORT(bp), 1);
}
udelay(10); udelay(10);
} }

View File

@ -652,6 +652,7 @@ struct adapter {
struct tid_info tids; struct tid_info tids;
void **tid_release_head; void **tid_release_head;
spinlock_t tid_release_lock; spinlock_t tid_release_lock;
struct workqueue_struct *workq;
struct work_struct tid_release_task; struct work_struct tid_release_task;
struct work_struct db_full_task; struct work_struct db_full_task;
struct work_struct db_drop_task; struct work_struct db_drop_task;

View File

@ -643,8 +643,6 @@ static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok)
return ret; return ret;
} }
static struct workqueue_struct *workq;
/** /**
* link_start - enable a port * link_start - enable a port
* @dev: the port to enable * @dev: the port to enable
@ -3340,7 +3338,7 @@ static void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
adap->tid_release_head = (void **)((uintptr_t)p | chan); adap->tid_release_head = (void **)((uintptr_t)p | chan);
if (!adap->tid_release_task_busy) { if (!adap->tid_release_task_busy) {
adap->tid_release_task_busy = true; adap->tid_release_task_busy = true;
queue_work(workq, &adap->tid_release_task); queue_work(adap->workq, &adap->tid_release_task);
} }
spin_unlock_bh(&adap->tid_release_lock); spin_unlock_bh(&adap->tid_release_lock);
} }
@ -4140,7 +4138,7 @@ void t4_db_full(struct adapter *adap)
notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL); notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL);
t4_set_reg_field(adap, SGE_INT_ENABLE3, t4_set_reg_field(adap, SGE_INT_ENABLE3,
DBFIFO_HP_INT | DBFIFO_LP_INT, 0); DBFIFO_HP_INT | DBFIFO_LP_INT, 0);
queue_work(workq, &adap->db_full_task); queue_work(adap->workq, &adap->db_full_task);
} }
} }
@ -4150,7 +4148,7 @@ void t4_db_dropped(struct adapter *adap)
disable_dbs(adap); disable_dbs(adap);
notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL); notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL);
} }
queue_work(workq, &adap->db_drop_task); queue_work(adap->workq, &adap->db_drop_task);
} }
static void uld_attach(struct adapter *adap, unsigned int uld) static void uld_attach(struct adapter *adap, unsigned int uld)
@ -6517,6 +6515,12 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_disable_device; goto out_disable_device;
} }
adapter->workq = create_singlethread_workqueue("cxgb4");
if (!adapter->workq) {
err = -ENOMEM;
goto out_free_adapter;
}
/* PCI device has been enabled */ /* PCI device has been enabled */
adapter->flags |= DEV_ENABLED; adapter->flags |= DEV_ENABLED;
@ -6715,6 +6719,9 @@ sriov:
out_unmap_bar0: out_unmap_bar0:
iounmap(adapter->regs); iounmap(adapter->regs);
out_free_adapter: out_free_adapter:
if (adapter->workq)
destroy_workqueue(adapter->workq);
kfree(adapter); kfree(adapter);
out_disable_device: out_disable_device:
pci_disable_pcie_error_reporting(pdev); pci_disable_pcie_error_reporting(pdev);
@ -6736,6 +6743,11 @@ static void remove_one(struct pci_dev *pdev)
if (adapter) { if (adapter) {
int i; int i;
/* Tear down per-adapter Work Queue first since it can contain
* references to our adapter data structure.
*/
destroy_workqueue(adapter->workq);
if (is_offload(adapter)) if (is_offload(adapter))
detach_ulds(adapter); detach_ulds(adapter);
@ -6788,20 +6800,14 @@ static int __init cxgb4_init_module(void)
{ {
int ret; int ret;
workq = create_singlethread_workqueue("cxgb4");
if (!workq)
return -ENOMEM;
/* Debugfs support is optional, just warn if this fails */ /* Debugfs support is optional, just warn if this fails */
cxgb4_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); cxgb4_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
if (!cxgb4_debugfs_root) if (!cxgb4_debugfs_root)
pr_warn("could not create debugfs entry, continuing\n"); pr_warn("could not create debugfs entry, continuing\n");
ret = pci_register_driver(&cxgb4_driver); ret = pci_register_driver(&cxgb4_driver);
if (ret < 0) { if (ret < 0)
debugfs_remove(cxgb4_debugfs_root); debugfs_remove(cxgb4_debugfs_root);
destroy_workqueue(workq);
}
register_inet6addr_notifier(&cxgb4_inet6addr_notifier); register_inet6addr_notifier(&cxgb4_inet6addr_notifier);
@ -6813,8 +6819,6 @@ static void __exit cxgb4_cleanup_module(void)
unregister_inet6addr_notifier(&cxgb4_inet6addr_notifier); unregister_inet6addr_notifier(&cxgb4_inet6addr_notifier);
pci_unregister_driver(&cxgb4_driver); pci_unregister_driver(&cxgb4_driver);
debugfs_remove(cxgb4_debugfs_root); /* NULL ok */ debugfs_remove(cxgb4_debugfs_root); /* NULL ok */
flush_workqueue(workq);
destroy_workqueue(workq);
} }
module_init(cxgb4_init_module); module_init(cxgb4_init_module);

View File

@ -2303,7 +2303,8 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
FW_EQ_ETH_CMD_PFN(adap->fn) | FW_EQ_ETH_CMD_VFN(0)); FW_EQ_ETH_CMD_PFN(adap->fn) | FW_EQ_ETH_CMD_VFN(0));
c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_ALLOC | c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_ALLOC |
FW_EQ_ETH_CMD_EQSTART | FW_LEN16(c)); FW_EQ_ETH_CMD_EQSTART | FW_LEN16(c));
c.viid_pkd = htonl(FW_EQ_ETH_CMD_VIID(pi->viid)); c.viid_pkd = htonl(FW_EQ_ETH_CMD_AUTOEQUEQE |
FW_EQ_ETH_CMD_VIID(pi->viid));
c.fetchszm_to_iqid = htonl(FW_EQ_ETH_CMD_HOSTFCMODE(2) | c.fetchszm_to_iqid = htonl(FW_EQ_ETH_CMD_HOSTFCMODE(2) |
FW_EQ_ETH_CMD_PCIECHN(pi->tx_chan) | FW_EQ_ETH_CMD_PCIECHN(pi->tx_chan) |
FW_EQ_ETH_CMD_FETCHRO(1) | FW_EQ_ETH_CMD_FETCHRO(1) |

View File

@ -1227,6 +1227,7 @@ struct fw_eq_eth_cmd {
#define FW_EQ_ETH_CMD_CIDXFTHRESH(x) ((x) << 16) #define FW_EQ_ETH_CMD_CIDXFTHRESH(x) ((x) << 16)
#define FW_EQ_ETH_CMD_EQSIZE(x) ((x) << 0) #define FW_EQ_ETH_CMD_EQSIZE(x) ((x) << 0)
#define FW_EQ_ETH_CMD_AUTOEQUEQE (1U << 30)
#define FW_EQ_ETH_CMD_VIID(x) ((x) << 16) #define FW_EQ_ETH_CMD_VIID(x) ((x) << 16)
struct fw_eq_ctrl_cmd { struct fw_eq_ctrl_cmd {

View File

@ -2250,7 +2250,8 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq,
cmd.alloc_to_len16 = cpu_to_be32(FW_EQ_ETH_CMD_ALLOC | cmd.alloc_to_len16 = cpu_to_be32(FW_EQ_ETH_CMD_ALLOC |
FW_EQ_ETH_CMD_EQSTART | FW_EQ_ETH_CMD_EQSTART |
FW_LEN16(cmd)); FW_LEN16(cmd));
cmd.viid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_VIID(pi->viid)); cmd.viid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_AUTOEQUEQE |
FW_EQ_ETH_CMD_VIID(pi->viid));
cmd.fetchszm_to_iqid = cmd.fetchszm_to_iqid =
cpu_to_be32(FW_EQ_ETH_CMD_HOSTFCMODE(SGE_HOSTFCMODE_STPG) | cpu_to_be32(FW_EQ_ETH_CMD_HOSTFCMODE(SGE_HOSTFCMODE_STPG) |
FW_EQ_ETH_CMD_PCIECHN(pi->port_id) | FW_EQ_ETH_CMD_PCIECHN(pi->port_id) |

View File

@ -275,6 +275,9 @@ struct fec_enet_private {
struct clk *clk_enet_out; struct clk *clk_enet_out;
struct clk *clk_ptp; struct clk *clk_ptp;
bool ptp_clk_on;
struct mutex ptp_clk_mutex;
/* The saved address of a sent-in-place packet/buffer, for skfree(). */ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
unsigned char *tx_bounce[TX_RING_SIZE]; unsigned char *tx_bounce[TX_RING_SIZE];
struct sk_buff *tx_skbuff[TX_RING_SIZE]; struct sk_buff *tx_skbuff[TX_RING_SIZE];
@ -335,7 +338,7 @@ struct fec_enet_private {
u32 cycle_speed; u32 cycle_speed;
int hwts_rx_en; int hwts_rx_en;
int hwts_tx_en; int hwts_tx_en;
struct timer_list time_keep; struct delayed_work time_keep;
struct regulator *reg_phy; struct regulator *reg_phy;
}; };

View File

@ -1611,17 +1611,27 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
goto failed_clk_enet_out; goto failed_clk_enet_out;
} }
if (fep->clk_ptp) { if (fep->clk_ptp) {
mutex_lock(&fep->ptp_clk_mutex);
ret = clk_prepare_enable(fep->clk_ptp); ret = clk_prepare_enable(fep->clk_ptp);
if (ret) if (ret) {
mutex_unlock(&fep->ptp_clk_mutex);
goto failed_clk_ptp; goto failed_clk_ptp;
} else {
fep->ptp_clk_on = true;
}
mutex_unlock(&fep->ptp_clk_mutex);
} }
} else { } else {
clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ahb);
clk_disable_unprepare(fep->clk_ipg); clk_disable_unprepare(fep->clk_ipg);
if (fep->clk_enet_out) if (fep->clk_enet_out)
clk_disable_unprepare(fep->clk_enet_out); clk_disable_unprepare(fep->clk_enet_out);
if (fep->clk_ptp) if (fep->clk_ptp) {
mutex_lock(&fep->ptp_clk_mutex);
clk_disable_unprepare(fep->clk_ptp); clk_disable_unprepare(fep->clk_ptp);
fep->ptp_clk_on = false;
mutex_unlock(&fep->ptp_clk_mutex);
}
} }
return 0; return 0;
@ -2625,6 +2635,8 @@ fec_probe(struct platform_device *pdev)
if (IS_ERR(fep->clk_enet_out)) if (IS_ERR(fep->clk_enet_out))
fep->clk_enet_out = NULL; fep->clk_enet_out = NULL;
fep->ptp_clk_on = false;
mutex_init(&fep->ptp_clk_mutex);
fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp"); fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
fep->bufdesc_ex = fep->bufdesc_ex =
pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX; pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
@ -2715,10 +2727,10 @@ fec_drv_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev); struct net_device *ndev = platform_get_drvdata(pdev);
struct fec_enet_private *fep = netdev_priv(ndev); struct fec_enet_private *fep = netdev_priv(ndev);
cancel_delayed_work_sync(&fep->time_keep);
cancel_work_sync(&fep->tx_timeout_work); cancel_work_sync(&fep->tx_timeout_work);
unregister_netdev(ndev); unregister_netdev(ndev);
fec_enet_mii_remove(fep); fec_enet_mii_remove(fep);
del_timer_sync(&fep->time_keep);
if (fep->reg_phy) if (fep->reg_phy)
regulator_disable(fep->reg_phy); regulator_disable(fep->reg_phy);
if (fep->ptp_clock) if (fep->ptp_clock)

View File

@ -245,12 +245,20 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp,
u64 ns; u64 ns;
unsigned long flags; unsigned long flags;
mutex_lock(&fep->ptp_clk_mutex);
/* Check the ptp clock */
if (!fep->ptp_clk_on) {
mutex_unlock(&fep->ptp_clk_mutex);
return -EINVAL;
}
ns = ts->tv_sec * 1000000000ULL; ns = ts->tv_sec * 1000000000ULL;
ns += ts->tv_nsec; ns += ts->tv_nsec;
spin_lock_irqsave(&fep->tmreg_lock, flags); spin_lock_irqsave(&fep->tmreg_lock, flags);
timecounter_init(&fep->tc, &fep->cc, ns); timecounter_init(&fep->tc, &fep->cc, ns);
spin_unlock_irqrestore(&fep->tmreg_lock, flags); spin_unlock_irqrestore(&fep->tmreg_lock, flags);
mutex_unlock(&fep->ptp_clk_mutex);
return 0; return 0;
} }
@ -338,17 +346,22 @@ int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr)
* fec_time_keep - call timecounter_read every second to avoid timer overrun * fec_time_keep - call timecounter_read every second to avoid timer overrun
* because ENET just support 32bit counter, will timeout in 4s * because ENET just support 32bit counter, will timeout in 4s
*/ */
static void fec_time_keep(unsigned long _data) static void fec_time_keep(struct work_struct *work)
{ {
struct fec_enet_private *fep = (struct fec_enet_private *)_data; struct delayed_work *dwork = to_delayed_work(work);
struct fec_enet_private *fep = container_of(dwork, struct fec_enet_private, time_keep);
u64 ns; u64 ns;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&fep->tmreg_lock, flags); mutex_lock(&fep->ptp_clk_mutex);
ns = timecounter_read(&fep->tc); if (fep->ptp_clk_on) {
spin_unlock_irqrestore(&fep->tmreg_lock, flags); spin_lock_irqsave(&fep->tmreg_lock, flags);
ns = timecounter_read(&fep->tc);
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
}
mutex_unlock(&fep->ptp_clk_mutex);
mod_timer(&fep->time_keep, jiffies + HZ); schedule_delayed_work(&fep->time_keep, HZ);
} }
/** /**
@ -386,15 +399,13 @@ void fec_ptp_init(struct platform_device *pdev)
fec_ptp_start_cyclecounter(ndev); fec_ptp_start_cyclecounter(ndev);
init_timer(&fep->time_keep); INIT_DELAYED_WORK(&fep->time_keep, fec_time_keep);
fep->time_keep.data = (unsigned long)fep;
fep->time_keep.function = fec_time_keep;
fep->time_keep.expires = jiffies + HZ;
add_timer(&fep->time_keep);
fep->ptp_clock = ptp_clock_register(&fep->ptp_caps, &pdev->dev); fep->ptp_clock = ptp_clock_register(&fep->ptp_caps, &pdev->dev);
if (IS_ERR(fep->ptp_clock)) { if (IS_ERR(fep->ptp_clock)) {
fep->ptp_clock = NULL; fep->ptp_clock = NULL;
pr_err("ptp_clock_register failed\n"); pr_err("ptp_clock_register failed\n");
} }
schedule_delayed_work(&fep->time_keep, HZ);
} }

View File

@ -292,6 +292,18 @@ failure:
atomic_add(buffers_added, &(pool->available)); atomic_add(buffers_added, &(pool->available));
} }
/*
* The final 8 bytes of the buffer list is a counter of frames dropped
* because there was not a buffer in the buffer list capable of holding
* the frame.
*/
static void ibmveth_update_rx_no_buffer(struct ibmveth_adapter *adapter)
{
__be64 *p = adapter->buffer_list_addr + 4096 - 8;
adapter->rx_no_buffer = be64_to_cpup(p);
}
/* replenish routine */ /* replenish routine */
static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
{ {
@ -307,8 +319,7 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
ibmveth_replenish_buffer_pool(adapter, pool); ibmveth_replenish_buffer_pool(adapter, pool);
} }
adapter->rx_no_buffer = *(u64 *)(((char*)adapter->buffer_list_addr) + ibmveth_update_rx_no_buffer(adapter);
4096 - 8);
} }
/* empty and free ana buffer pool - also used to do cleanup in error paths */ /* empty and free ana buffer pool - also used to do cleanup in error paths */
@ -698,8 +709,7 @@ static int ibmveth_close(struct net_device *netdev)
free_irq(netdev->irq, netdev); free_irq(netdev->irq, netdev);
adapter->rx_no_buffer = *(u64 *)(((char *)adapter->buffer_list_addr) + ibmveth_update_rx_no_buffer(adapter);
4096 - 8);
ibmveth_cleanup(adapter); ibmveth_cleanup(adapter);

View File

@ -247,7 +247,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
u32 prttsyn_stat; u32 prttsyn_stat;
int n; int n;
if (pf->flags & I40E_FLAG_PTP) if (!(pf->flags & I40E_FLAG_PTP))
return; return;
prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1); prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);

View File

@ -1003,11 +1003,19 @@ int i40e_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode, static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
u32 v_retval, u8 *msg, u16 msglen) u32 v_retval, u8 *msg, u16 msglen)
{ {
struct i40e_pf *pf = vf->pf; struct i40e_pf *pf;
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw;
int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id; int abs_vf_id;
i40e_status aq_ret; i40e_status aq_ret;
/* validate the request */
if (!vf || vf->vf_id >= vf->pf->num_alloc_vfs)
return -EINVAL;
pf = vf->pf;
hw = &pf->hw;
abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
/* single place to detect unsuccessful return values */ /* single place to detect unsuccessful return values */
if (v_retval) { if (v_retval) {
vf->num_invalid_msgs++; vf->num_invalid_msgs++;
@ -1928,17 +1936,20 @@ static void i40e_vc_vf_broadcast(struct i40e_pf *pf,
{ {
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
struct i40e_vf *vf = pf->vf; struct i40e_vf *vf = pf->vf;
int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
int i; int i;
for (i = 0; i < pf->num_alloc_vfs; i++) { for (i = 0; i < pf->num_alloc_vfs; i++, vf++) {
int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
/* Not all vfs are enabled so skip the ones that are not */
if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states) &&
!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states))
continue;
/* Ignore return value on purpose - a given VF may fail, but /* Ignore return value on purpose - a given VF may fail, but
* we need to keep going and send to all of them * we need to keep going and send to all of them
*/ */
i40e_aq_send_msg_to_vf(hw, abs_vf_id, v_opcode, v_retval, i40e_aq_send_msg_to_vf(hw, abs_vf_id, v_opcode, v_retval,
msg, msglen, NULL); msg, msglen, NULL);
vf++;
abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
} }
} }
@ -1954,12 +1965,12 @@ void i40e_vc_notify_link_state(struct i40e_pf *pf)
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
struct i40e_vf *vf = pf->vf; struct i40e_vf *vf = pf->vf;
struct i40e_link_status *ls = &pf->hw.phy.link_info; struct i40e_link_status *ls = &pf->hw.phy.link_info;
int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
int i; int i;
pfe.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE; pfe.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE;
pfe.severity = I40E_PF_EVENT_SEVERITY_INFO; pfe.severity = I40E_PF_EVENT_SEVERITY_INFO;
for (i = 0; i < pf->num_alloc_vfs; i++) { for (i = 0; i < pf->num_alloc_vfs; i++, vf++) {
int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
if (vf->link_forced) { if (vf->link_forced) {
pfe.event_data.link_event.link_status = vf->link_up; pfe.event_data.link_event.link_status = vf->link_up;
pfe.event_data.link_event.link_speed = pfe.event_data.link_event.link_speed =
@ -1972,8 +1983,6 @@ void i40e_vc_notify_link_state(struct i40e_pf *pf)
i40e_aq_send_msg_to_vf(hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT, i40e_aq_send_msg_to_vf(hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT,
0, (u8 *)&pfe, sizeof(pfe), 0, (u8 *)&pfe, sizeof(pfe),
NULL); NULL);
vf++;
abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
} }
} }
@ -2002,7 +2011,18 @@ void i40e_vc_notify_reset(struct i40e_pf *pf)
void i40e_vc_notify_vf_reset(struct i40e_vf *vf) void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
{ {
struct i40e_virtchnl_pf_event pfe; struct i40e_virtchnl_pf_event pfe;
int abs_vf_id = vf->vf_id + vf->pf->hw.func_caps.vf_base_id; int abs_vf_id;
/* validate the request */
if (!vf || vf->vf_id >= vf->pf->num_alloc_vfs)
return;
/* verify if the VF is in either init or active before proceeding */
if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states) &&
!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states))
return;
abs_vf_id = vf->vf_id + vf->pf->hw.func_caps.vf_base_id;
pfe.event = I40E_VIRTCHNL_EVENT_RESET_IMPENDING; pfe.event = I40E_VIRTCHNL_EVENT_RESET_IMPENDING;
pfe.severity = I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM; pfe.severity = I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM;

View File

@ -268,7 +268,7 @@ struct qlcnic_fdt {
u16 cksum; u16 cksum;
u16 unused; u16 unused;
u8 model[16]; u8 model[16];
u16 mfg_id; u8 mfg_id;
u16 id; u16 id;
u8 flag; u8 flag;
u8 erase_cmd; u8 erase_cmd;
@ -2362,6 +2362,19 @@ static inline u32 qlcnic_get_vnic_func_count(struct qlcnic_adapter *adapter)
return QLC_DEFAULT_VNIC_COUNT; return QLC_DEFAULT_VNIC_COUNT;
} }
static inline void qlcnic_swap32_buffer(u32 *buffer, int count)
{
#if defined(__BIG_ENDIAN)
u32 *tmp = buffer;
int i;
for (i = 0; i < count; i++) {
*tmp = swab32(*tmp);
tmp++;
}
#endif
}
#ifdef CONFIG_QLCNIC_HWMON #ifdef CONFIG_QLCNIC_HWMON
void qlcnic_register_hwmon_dev(struct qlcnic_adapter *); void qlcnic_register_hwmon_dev(struct qlcnic_adapter *);
void qlcnic_unregister_hwmon_dev(struct qlcnic_adapter *); void qlcnic_unregister_hwmon_dev(struct qlcnic_adapter *);

View File

@ -2603,7 +2603,7 @@ int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *adapter,
} }
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_DIRECT_WINDOW, qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_DIRECT_WINDOW,
(addr)); (addr & 0xFFFF0000));
range = flash_offset + (count * sizeof(u32)); range = flash_offset + (count * sizeof(u32));
/* Check if data is spread across multiple sectors */ /* Check if data is spread across multiple sectors */
@ -2753,7 +2753,7 @@ int qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *adapter)
ret = qlcnic_83xx_lockless_flash_read32(adapter, QLCNIC_FDT_LOCATION, ret = qlcnic_83xx_lockless_flash_read32(adapter, QLCNIC_FDT_LOCATION,
(u8 *)&adapter->ahw->fdt, (u8 *)&adapter->ahw->fdt,
count); count);
qlcnic_swap32_buffer((u32 *)&adapter->ahw->fdt, count);
qlcnic_83xx_unlock_flash(adapter); qlcnic_83xx_unlock_flash(adapter);
return ret; return ret;
} }
@ -2788,7 +2788,7 @@ int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
addr1 = (sector_start_addr & 0xFF) << 16; addr1 = (sector_start_addr & 0xFF) << 16;
addr2 = (sector_start_addr & 0xFF0000) >> 16; addr2 = (sector_start_addr & 0xFF0000) >> 16;
reversed_addr = addr1 | addr2; reversed_addr = addr1 | addr2 | (sector_start_addr & 0xFF00);
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
reversed_addr); reversed_addr);

View File

@ -1378,31 +1378,45 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
{ {
struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info; struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;
const struct firmware *fw = fw_info->fw; const struct firmware *fw = fw_info->fw;
u32 dest, *p_cache; u32 dest, *p_cache, *temp;
int i, ret = -EIO; int i, ret = -EIO;
__le32 *temp_le;
u8 data[16]; u8 data[16];
size_t size; size_t size;
u64 addr; u64 addr;
temp = kzalloc(fw->size, GFP_KERNEL);
if (!temp) {
release_firmware(fw);
fw_info->fw = NULL;
return -ENOMEM;
}
temp_le = (__le32 *)fw->data;
/* FW image in file is in little endian, swap the data to nullify
* the effect of writel() operation on big endian platform.
*/
for (i = 0; i < fw->size / sizeof(u32); i++)
temp[i] = __le32_to_cpu(temp_le[i]);
dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR); dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR);
size = (fw->size & ~0xF); size = (fw->size & ~0xF);
p_cache = (u32 *)fw->data; p_cache = temp;
addr = (u64)dest; addr = (u64)dest;
ret = qlcnic_ms_mem_write128(adapter, addr, ret = qlcnic_ms_mem_write128(adapter, addr,
p_cache, size / 16); p_cache, size / 16);
if (ret) { if (ret) {
dev_err(&adapter->pdev->dev, "MS memory write failed\n"); dev_err(&adapter->pdev->dev, "MS memory write failed\n");
release_firmware(fw); goto exit;
fw_info->fw = NULL;
return -EIO;
} }
/* alignment check */ /* alignment check */
if (fw->size & 0xF) { if (fw->size & 0xF) {
addr = dest + size; addr = dest + size;
for (i = 0; i < (fw->size & 0xF); i++) for (i = 0; i < (fw->size & 0xF); i++)
data[i] = fw->data[size + i]; data[i] = temp[size + i];
for (; i < 16; i++) for (; i < 16; i++)
data[i] = 0; data[i] = 0;
ret = qlcnic_ms_mem_write128(adapter, addr, ret = qlcnic_ms_mem_write128(adapter, addr,
@ -1410,15 +1424,16 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
if (ret) { if (ret) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"MS memory write failed\n"); "MS memory write failed\n");
release_firmware(fw); goto exit;
fw_info->fw = NULL;
return -EIO;
} }
} }
exit:
release_firmware(fw); release_firmware(fw);
fw_info->fw = NULL; fw_info->fw = NULL;
kfree(temp);
return 0; return ret;
} }
static void qlcnic_83xx_dump_pause_control_regs(struct qlcnic_adapter *adapter) static void qlcnic_83xx_dump_pause_control_regs(struct qlcnic_adapter *adapter)

View File

@ -47,15 +47,26 @@ struct qlcnic_common_entry_hdr {
u32 type; u32 type;
u32 offset; u32 offset;
u32 cap_size; u32 cap_size;
#if defined(__LITTLE_ENDIAN)
u8 mask; u8 mask;
u8 rsvd[2]; u8 rsvd[2];
u8 flags; u8 flags;
#else
u8 flags;
u8 rsvd[2];
u8 mask;
#endif
} __packed; } __packed;
struct __crb { struct __crb {
u32 addr; u32 addr;
#if defined(__LITTLE_ENDIAN)
u8 stride; u8 stride;
u8 rsvd1[3]; u8 rsvd1[3];
#else
u8 rsvd1[3];
u8 stride;
#endif
u32 data_size; u32 data_size;
u32 no_ops; u32 no_ops;
u32 rsvd2[4]; u32 rsvd2[4];
@ -63,15 +74,28 @@ struct __crb {
struct __ctrl { struct __ctrl {
u32 addr; u32 addr;
#if defined(__LITTLE_ENDIAN)
u8 stride; u8 stride;
u8 index_a; u8 index_a;
u16 timeout; u16 timeout;
#else
u16 timeout;
u8 index_a;
u8 stride;
#endif
u32 data_size; u32 data_size;
u32 no_ops; u32 no_ops;
#if defined(__LITTLE_ENDIAN)
u8 opcode; u8 opcode;
u8 index_v; u8 index_v;
u8 shl_val; u8 shl_val;
u8 shr_val; u8 shr_val;
#else
u8 shr_val;
u8 shl_val;
u8 index_v;
u8 opcode;
#endif
u32 val1; u32 val1;
u32 val2; u32 val2;
u32 val3; u32 val3;
@ -79,16 +103,27 @@ struct __ctrl {
struct __cache { struct __cache {
u32 addr; u32 addr;
#if defined(__LITTLE_ENDIAN)
u16 stride; u16 stride;
u16 init_tag_val; u16 init_tag_val;
#else
u16 init_tag_val;
u16 stride;
#endif
u32 size; u32 size;
u32 no_ops; u32 no_ops;
u32 ctrl_addr; u32 ctrl_addr;
u32 ctrl_val; u32 ctrl_val;
u32 read_addr; u32 read_addr;
#if defined(__LITTLE_ENDIAN)
u8 read_addr_stride; u8 read_addr_stride;
u8 read_addr_num; u8 read_addr_num;
u8 rsvd1[2]; u8 rsvd1[2];
#else
u8 rsvd1[2];
u8 read_addr_num;
u8 read_addr_stride;
#endif
} __packed; } __packed;
struct __ocm { struct __ocm {
@ -122,23 +157,39 @@ struct __mux {
struct __queue { struct __queue {
u32 sel_addr; u32 sel_addr;
#if defined(__LITTLE_ENDIAN)
u16 stride; u16 stride;
u8 rsvd[2]; u8 rsvd[2];
#else
u8 rsvd[2];
u16 stride;
#endif
u32 size; u32 size;
u32 no_ops; u32 no_ops;
u8 rsvd2[8]; u8 rsvd2[8];
u32 read_addr; u32 read_addr;
#if defined(__LITTLE_ENDIAN)
u8 read_addr_stride; u8 read_addr_stride;
u8 read_addr_cnt; u8 read_addr_cnt;
u8 rsvd3[2]; u8 rsvd3[2];
#else
u8 rsvd3[2];
u8 read_addr_cnt;
u8 read_addr_stride;
#endif
} __packed; } __packed;
struct __pollrd { struct __pollrd {
u32 sel_addr; u32 sel_addr;
u32 read_addr; u32 read_addr;
u32 sel_val; u32 sel_val;
#if defined(__LITTLE_ENDIAN)
u16 sel_val_stride; u16 sel_val_stride;
u16 no_ops; u16 no_ops;
#else
u16 no_ops;
u16 sel_val_stride;
#endif
u32 poll_wait; u32 poll_wait;
u32 poll_mask; u32 poll_mask;
u32 data_size; u32 data_size;
@ -153,9 +204,15 @@ struct __mux2 {
u32 no_ops; u32 no_ops;
u32 sel_val_mask; u32 sel_val_mask;
u32 read_addr; u32 read_addr;
#if defined(__LITTLE_ENDIAN)
u8 sel_val_stride; u8 sel_val_stride;
u8 data_size; u8 data_size;
u8 rsvd[2]; u8 rsvd[2];
#else
u8 rsvd[2];
u8 data_size;
u8 sel_val_stride;
#endif
} __packed; } __packed;
struct __pollrdmwr { struct __pollrdmwr {

View File

@ -280,6 +280,7 @@ static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
if (ret != 0) if (ret != 0)
return ret; return ret;
qlcnic_read_crb(adapter, buf, offset, size); qlcnic_read_crb(adapter, buf, offset, size);
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
return size; return size;
} }
@ -296,6 +297,7 @@ static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
if (ret != 0) if (ret != 0)
return ret; return ret;
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
qlcnic_write_crb(adapter, buf, offset, size); qlcnic_write_crb(adapter, buf, offset, size);
return size; return size;
} }
@ -329,6 +331,7 @@ static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
return -EIO; return -EIO;
memcpy(buf, &data, size); memcpy(buf, &data, size);
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
return size; return size;
} }
@ -346,6 +349,7 @@ static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
if (ret != 0) if (ret != 0)
return ret; return ret;
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
memcpy(&data, buf, size); memcpy(&data, buf, size);
if (qlcnic_pci_mem_write_2M(adapter, offset, data)) if (qlcnic_pci_mem_write_2M(adapter, offset, data))
@ -412,6 +416,7 @@ static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
if (rem) if (rem)
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
pm_cfg = (struct qlcnic_pm_func_cfg *)buf; pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
ret = validate_pm_config(adapter, pm_cfg, count); ret = validate_pm_config(adapter, pm_cfg, count);
@ -474,6 +479,7 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
pm_cfg[pci_func].dest_npar = 0; pm_cfg[pci_func].dest_npar = 0;
pm_cfg[pci_func].pci_func = i; pm_cfg[pci_func].pci_func = i;
} }
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
return size; return size;
} }
@ -555,6 +561,7 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
if (rem) if (rem)
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
esw_cfg = (struct qlcnic_esw_func_cfg *)buf; esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
ret = validate_esw_config(adapter, esw_cfg, count); ret = validate_esw_config(adapter, esw_cfg, count);
if (ret) if (ret)
@ -649,6 +656,7 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func])) if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func]))
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
} }
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
return size; return size;
} }
@ -688,6 +696,7 @@ static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
if (rem) if (rem)
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
np_cfg = (struct qlcnic_npar_func_cfg *)buf; np_cfg = (struct qlcnic_npar_func_cfg *)buf;
ret = validate_npar_config(adapter, np_cfg, count); ret = validate_npar_config(adapter, np_cfg, count);
if (ret) if (ret)
@ -759,6 +768,7 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
np_cfg[pci_func].max_tx_queues = nic_info.max_tx_ques; np_cfg[pci_func].max_tx_queues = nic_info.max_tx_ques;
np_cfg[pci_func].max_rx_queues = nic_info.max_rx_ques; np_cfg[pci_func].max_rx_queues = nic_info.max_rx_ques;
} }
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
return size; return size;
} }
@ -916,6 +926,7 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
pci_cfg = (struct qlcnic_pci_func_cfg *)buf; pci_cfg = (struct qlcnic_pci_func_cfg *)buf;
count = size / sizeof(struct qlcnic_pci_func_cfg); count = size / sizeof(struct qlcnic_pci_func_cfg);
qlcnic_swap32_buffer((u32 *)pci_info, size / sizeof(u32));
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
pci_cfg[i].pci_func = pci_info[i].id; pci_cfg[i].pci_func = pci_info[i].id;
pci_cfg[i].func_type = pci_info[i].type; pci_cfg[i].func_type = pci_info[i].type;
@ -969,6 +980,7 @@ static ssize_t qlcnic_83xx_sysfs_flash_read_handler(struct file *filp,
} }
qlcnic_83xx_unlock_flash(adapter); qlcnic_83xx_unlock_flash(adapter);
qlcnic_swap32_buffer((u32 *)p_read_buf, count);
memcpy(buf, p_read_buf, size); memcpy(buf, p_read_buf, size);
kfree(p_read_buf); kfree(p_read_buf);
@ -986,9 +998,10 @@ static int qlcnic_83xx_sysfs_flash_bulk_write(struct qlcnic_adapter *adapter,
if (!p_cache) if (!p_cache)
return -ENOMEM; return -ENOMEM;
count = size / sizeof(u32);
qlcnic_swap32_buffer((u32 *)buf, count);
memcpy(p_cache, buf, size); memcpy(p_cache, buf, size);
p_src = p_cache; p_src = p_cache;
count = size / sizeof(u32);
if (qlcnic_83xx_lock_flash(adapter) != 0) { if (qlcnic_83xx_lock_flash(adapter) != 0) {
kfree(p_cache); kfree(p_cache);
@ -1053,6 +1066,7 @@ static int qlcnic_83xx_sysfs_flash_write(struct qlcnic_adapter *adapter,
if (!p_cache) if (!p_cache)
return -ENOMEM; return -ENOMEM;
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
memcpy(p_cache, buf, size); memcpy(p_cache, buf, size);
p_src = p_cache; p_src = p_cache;
count = size / sizeof(u32); count = size / sizeof(u32);

View File

@ -739,7 +739,10 @@ static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct macvlan_dev *vlan = netdev_priv(dev); struct macvlan_dev *vlan = netdev_priv(dev);
int err = -EINVAL; int err = -EINVAL;
if (!vlan->port->passthru) /* Support unicast filter only on passthru devices.
* Multicast filter should be allowed on all devices.
*/
if (!vlan->port->passthru && is_unicast_ether_addr(addr))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (flags & NLM_F_REPLACE) if (flags & NLM_F_REPLACE)
@ -760,7 +763,10 @@ static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
struct macvlan_dev *vlan = netdev_priv(dev); struct macvlan_dev *vlan = netdev_priv(dev);
int err = -EINVAL; int err = -EINVAL;
if (!vlan->port->passthru) /* Support unicast filter only on passthru devices.
* Multicast filter should be allowed on all devices.
*/
if (!vlan->port->passthru && is_unicast_ether_addr(addr))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (is_unicast_ether_addr(addr)) if (is_unicast_ether_addr(addr))

View File

@ -157,6 +157,23 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
return bcm7xxx_28nm_afe_config_init(phydev); return bcm7xxx_28nm_afe_config_init(phydev);
} }
static int bcm7xxx_28nm_resume(struct phy_device *phydev)
{
int ret;
/* Re-apply workarounds coming out suspend/resume */
ret = bcm7xxx_28nm_config_init(phydev);
if (ret)
return ret;
/* 28nm Gigabit PHYs come out of reset without any half-duplex
* or "hub" compliant advertised mode, fix that. This does not
* cause any problems with the PHY library since genphy_config_aneg()
* gracefully handles auto-negotiated and forced modes.
*/
return genphy_config_aneg(phydev);
}
static int phy_set_clr_bits(struct phy_device *dev, int location, static int phy_set_clr_bits(struct phy_device *dev, int location,
int set_mask, int clr_mask) int set_mask, int clr_mask)
{ {
@ -212,7 +229,7 @@ static int bcm7xxx_config_init(struct phy_device *phydev)
} }
/* Workaround for putting the PHY in IDDQ mode, required /* Workaround for putting the PHY in IDDQ mode, required
* for all BCM7XXX PHYs * for all BCM7XXX 40nm and 65nm PHYs
*/ */
static int bcm7xxx_suspend(struct phy_device *phydev) static int bcm7xxx_suspend(struct phy_device *phydev)
{ {
@ -257,8 +274,7 @@ static struct phy_driver bcm7xxx_driver[] = {
.config_init = bcm7xxx_28nm_afe_config_init, .config_init = bcm7xxx_28nm_afe_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.suspend = bcm7xxx_suspend, .resume = bcm7xxx_28nm_resume,
.resume = bcm7xxx_28nm_afe_config_init,
.driver = { .owner = THIS_MODULE }, .driver = { .owner = THIS_MODULE },
}, { }, {
.phy_id = PHY_ID_BCM7439, .phy_id = PHY_ID_BCM7439,
@ -270,8 +286,7 @@ static struct phy_driver bcm7xxx_driver[] = {
.config_init = bcm7xxx_28nm_afe_config_init, .config_init = bcm7xxx_28nm_afe_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.suspend = bcm7xxx_suspend, .resume = bcm7xxx_28nm_resume,
.resume = bcm7xxx_28nm_afe_config_init,
.driver = { .owner = THIS_MODULE }, .driver = { .owner = THIS_MODULE },
}, { }, {
.phy_id = PHY_ID_BCM7445, .phy_id = PHY_ID_BCM7445,
@ -283,21 +298,7 @@ static struct phy_driver bcm7xxx_driver[] = {
.config_init = bcm7xxx_28nm_config_init, .config_init = bcm7xxx_28nm_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.suspend = bcm7xxx_suspend, .resume = bcm7xxx_28nm_afe_config_init,
.resume = bcm7xxx_28nm_config_init,
.driver = { .owner = THIS_MODULE },
}, {
.name = "Broadcom BCM7XXX 28nm",
.phy_id = PHY_ID_BCM7XXX_28,
.phy_id_mask = PHY_BCM_OUI_MASK,
.features = PHY_GBIT_FEATURES |
SUPPORTED_Pause | SUPPORTED_Asym_Pause,
.flags = PHY_IS_INTERNAL,
.config_init = bcm7xxx_28nm_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
.suspend = bcm7xxx_suspend,
.resume = bcm7xxx_28nm_config_init,
.driver = { .owner = THIS_MODULE }, .driver = { .owner = THIS_MODULE },
}, { }, {
.phy_id = PHY_BCM_OUI_4, .phy_id = PHY_BCM_OUI_4,
@ -331,7 +332,6 @@ static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
{ PHY_ID_BCM7366, 0xfffffff0, }, { PHY_ID_BCM7366, 0xfffffff0, },
{ PHY_ID_BCM7439, 0xfffffff0, }, { PHY_ID_BCM7439, 0xfffffff0, },
{ PHY_ID_BCM7445, 0xfffffff0, }, { PHY_ID_BCM7445, 0xfffffff0, },
{ PHY_ID_BCM7XXX_28, 0xfffffc00 },
{ PHY_BCM_OUI_4, 0xffff0000 }, { PHY_BCM_OUI_4, 0xffff0000 },
{ PHY_BCM_OUI_5, 0xffffff00 }, { PHY_BCM_OUI_5, 0xffffff00 },
{ } { }

View File

@ -42,6 +42,22 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev)
} }
static int smsc_phy_config_init(struct phy_device *phydev) static int smsc_phy_config_init(struct phy_device *phydev)
{
int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
if (rc < 0)
return rc;
/* Enable energy detect mode for this SMSC Transceivers */
rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
rc | MII_LAN83C185_EDPWRDOWN);
if (rc < 0)
return rc;
return smsc_phy_ack_interrupt(phydev);
}
static int smsc_phy_reset(struct phy_device *phydev)
{ {
int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES); int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
if (rc < 0) if (rc < 0)
@ -66,18 +82,7 @@ static int smsc_phy_config_init(struct phy_device *phydev)
rc = phy_read(phydev, MII_BMCR); rc = phy_read(phydev, MII_BMCR);
} while (rc & BMCR_RESET); } while (rc & BMCR_RESET);
} }
return 0;
rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
if (rc < 0)
return rc;
/* Enable energy detect mode for this SMSC Transceivers */
rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
rc | MII_LAN83C185_EDPWRDOWN);
if (rc < 0)
return rc;
return smsc_phy_ack_interrupt (phydev);
} }
static int lan911x_config_init(struct phy_device *phydev) static int lan911x_config_init(struct phy_device *phydev)
@ -142,6 +147,7 @@ static struct phy_driver smsc_phy_driver[] = {
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.config_init = smsc_phy_config_init, .config_init = smsc_phy_config_init,
.soft_reset = smsc_phy_reset,
/* IRQ related */ /* IRQ related */
.ack_interrupt = smsc_phy_ack_interrupt, .ack_interrupt = smsc_phy_ack_interrupt,
@ -164,6 +170,7 @@ static struct phy_driver smsc_phy_driver[] = {
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.config_init = smsc_phy_config_init, .config_init = smsc_phy_config_init,
.soft_reset = smsc_phy_reset,
/* IRQ related */ /* IRQ related */
.ack_interrupt = smsc_phy_ack_interrupt, .ack_interrupt = smsc_phy_ack_interrupt,
@ -186,6 +193,7 @@ static struct phy_driver smsc_phy_driver[] = {
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.config_init = smsc_phy_config_init, .config_init = smsc_phy_config_init,
.soft_reset = smsc_phy_reset,
/* IRQ related */ /* IRQ related */
.ack_interrupt = smsc_phy_ack_interrupt, .ack_interrupt = smsc_phy_ack_interrupt,
@ -230,6 +238,7 @@ static struct phy_driver smsc_phy_driver[] = {
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = lan87xx_read_status, .read_status = lan87xx_read_status,
.config_init = smsc_phy_config_init, .config_init = smsc_phy_config_init,
.soft_reset = smsc_phy_reset,
/* IRQ related */ /* IRQ related */
.ack_interrupt = smsc_phy_ack_interrupt, .ack_interrupt = smsc_phy_ack_interrupt,

View File

@ -16,7 +16,6 @@
#define PHY_ID_BCM7366 0x600d8490 #define PHY_ID_BCM7366 0x600d8490
#define PHY_ID_BCM7439 0x600d8480 #define PHY_ID_BCM7439 0x600d8480
#define PHY_ID_BCM7445 0x600d8510 #define PHY_ID_BCM7445 0x600d8510
#define PHY_ID_BCM7XXX_28 0x600d8400
#define PHY_BCM_OUI_MASK 0xfffffc00 #define PHY_BCM_OUI_MASK 0xfffffc00
#define PHY_BCM_OUI_1 0x00206000 #define PHY_BCM_OUI_1 0x00206000

View File

@ -410,9 +410,11 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
priv->lane2_ops = NULL; priv->lane2_ops = NULL;
if (priv->lane_version > 1) if (priv->lane_version > 1)
priv->lane2_ops = &lane2_ops; priv->lane2_ops = &lane2_ops;
rtnl_lock();
if (dev_set_mtu(dev, mesg->content.config.mtu)) if (dev_set_mtu(dev, mesg->content.config.mtu))
pr_info("%s: change_mtu to %d failed\n", pr_info("%s: change_mtu to %d failed\n",
dev->name, mesg->content.config.mtu); dev->name, mesg->content.config.mtu);
rtnl_unlock();
priv->is_proxy = mesg->content.config.is_proxy; priv->is_proxy = mesg->content.config.is_proxy;
break; break;
case l_flush_tran_id: case l_flush_tran_id:

View File

@ -188,7 +188,7 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node,
/* Reached the end of the list, so insert after 'frag_entry_last'. */ /* Reached the end of the list, so insert after 'frag_entry_last'. */
if (likely(frag_entry_last)) { if (likely(frag_entry_last)) {
hlist_add_behind(&frag_entry_last->list, &frag_entry_new->list); hlist_add_behind(&frag_entry_new->list, &frag_entry_last->list);
chain->size += skb->len - hdr_size; chain->size += skb->len - hdr_size;
chain->timestamp = jiffies; chain->timestamp = jiffies;
ret = true; ret = true;

View File

@ -643,7 +643,7 @@ static int fib6_commit_metrics(struct dst_entry *dst,
if (dst->flags & DST_HOST) { if (dst->flags & DST_HOST) {
mp = dst_metrics_write_ptr(dst); mp = dst_metrics_write_ptr(dst);
} else { } else {
mp = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); mp = kzalloc(sizeof(u32) * RTAX_MAX, GFP_ATOMIC);
if (!mp) if (!mp)
return -ENOMEM; return -ENOMEM;
dst_init_metrics(dst, mp, 0); dst_init_metrics(dst, mp, 0);

View File

@ -42,6 +42,9 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
static int make_writable(struct sk_buff *skb, int write_len) static int make_writable(struct sk_buff *skb, int write_len)
{ {
if (!pskb_may_pull(skb, write_len))
return -ENOMEM;
if (!skb_cloned(skb) || skb_clone_writable(skb, write_len)) if (!skb_cloned(skb) || skb_clone_writable(skb, write_len))
return 0; return 0;
@ -70,6 +73,8 @@ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)
vlan_set_encap_proto(skb, vhdr); vlan_set_encap_proto(skb, vhdr);
skb->mac_header += VLAN_HLEN; skb->mac_header += VLAN_HLEN;
if (skb_network_offset(skb) < ETH_HLEN)
skb_set_network_header(skb, ETH_HLEN);
skb_reset_mac_len(skb); skb_reset_mac_len(skb);
return 0; return 0;

View File

@ -632,6 +632,7 @@ static void init_prb_bdqc(struct packet_sock *po,
p1->tov_in_jiffies = msecs_to_jiffies(p1->retire_blk_tov); p1->tov_in_jiffies = msecs_to_jiffies(p1->retire_blk_tov);
p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv; p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv;
p1->max_frame_len = p1->kblk_size - BLK_PLUS_PRIV(p1->blk_sizeof_priv);
prb_init_ft_ops(p1, req_u); prb_init_ft_ops(p1, req_u);
prb_setup_retire_blk_timer(po, tx_ring); prb_setup_retire_blk_timer(po, tx_ring);
prb_open_block(p1, pbd); prb_open_block(p1, pbd);
@ -1942,6 +1943,18 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
if ((int)snaplen < 0) if ((int)snaplen < 0)
snaplen = 0; snaplen = 0;
} }
} else if (unlikely(macoff + snaplen >
GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len)) {
u32 nval;
nval = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len - macoff;
pr_err_once("tpacket_rcv: packet too big, clamped from %u to %u. macoff=%u\n",
snaplen, nval, macoff);
snaplen = nval;
if (unlikely((int)snaplen < 0)) {
snaplen = 0;
macoff = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len;
}
} }
spin_lock(&sk->sk_receive_queue.lock); spin_lock(&sk->sk_receive_queue.lock);
h.raw = packet_current_rx_frame(po, skb, h.raw = packet_current_rx_frame(po, skb,
@ -3783,6 +3796,10 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
goto out; goto out;
if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) if (unlikely(req->tp_block_size & (PAGE_SIZE - 1)))
goto out; goto out;
if (po->tp_version >= TPACKET_V3 &&
(int)(req->tp_block_size -
BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
goto out;
if (unlikely(req->tp_frame_size < po->tp_hdrlen + if (unlikely(req->tp_frame_size < po->tp_hdrlen +
po->tp_reserve)) po->tp_reserve))
goto out; goto out;

View File

@ -29,6 +29,7 @@ struct tpacket_kbdq_core {
char *pkblk_start; char *pkblk_start;
char *pkblk_end; char *pkblk_end;
int kblk_size; int kblk_size;
unsigned int max_frame_len;
unsigned int knum_blocks; unsigned int knum_blocks;
uint64_t knxt_seq_num; uint64_t knxt_seq_num;
char *prev; char *prev;

View File

@ -159,7 +159,6 @@ struct cbq_sched_data {
struct cbq_class *tx_borrowed; struct cbq_class *tx_borrowed;
int tx_len; int tx_len;
psched_time_t now; /* Cached timestamp */ psched_time_t now; /* Cached timestamp */
psched_time_t now_rt; /* Cached real time */
unsigned int pmask; unsigned int pmask;
struct hrtimer delay_timer; struct hrtimer delay_timer;
@ -353,12 +352,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl)
int toplevel = q->toplevel; int toplevel = q->toplevel;
if (toplevel > cl->level && !(qdisc_is_throttled(cl->q))) { if (toplevel > cl->level && !(qdisc_is_throttled(cl->q))) {
psched_time_t now; psched_time_t now = psched_get_time();
psched_tdiff_t incr;
now = psched_get_time();
incr = now - q->now_rt;
now = q->now + incr;
do { do {
if (cl->undertime < now) { if (cl->undertime < now) {
@ -700,8 +694,13 @@ cbq_update(struct cbq_sched_data *q)
struct cbq_class *this = q->tx_class; struct cbq_class *this = q->tx_class;
struct cbq_class *cl = this; struct cbq_class *cl = this;
int len = q->tx_len; int len = q->tx_len;
psched_time_t now;
q->tx_class = NULL; q->tx_class = NULL;
/* Time integrator. We calculate EOS time
* by adding expected packet transmission time.
*/
now = q->now + L2T(&q->link, len);
for ( ; cl; cl = cl->share) { for ( ; cl; cl = cl->share) {
long avgidle = cl->avgidle; long avgidle = cl->avgidle;
@ -717,7 +716,7 @@ cbq_update(struct cbq_sched_data *q)
* idle = (now - last) - last_pktlen/rate * idle = (now - last) - last_pktlen/rate
*/ */
idle = q->now - cl->last; idle = now - cl->last;
if ((unsigned long)idle > 128*1024*1024) { if ((unsigned long)idle > 128*1024*1024) {
avgidle = cl->maxidle; avgidle = cl->maxidle;
} else { } else {
@ -761,7 +760,7 @@ cbq_update(struct cbq_sched_data *q)
idle -= L2T(&q->link, len); idle -= L2T(&q->link, len);
idle += L2T(cl, len); idle += L2T(cl, len);
cl->undertime = q->now + idle; cl->undertime = now + idle;
} else { } else {
/* Underlimit */ /* Underlimit */
@ -771,7 +770,8 @@ cbq_update(struct cbq_sched_data *q)
else else
cl->avgidle = avgidle; cl->avgidle = avgidle;
} }
cl->last = q->now; if ((s64)(now - cl->last) > 0)
cl->last = now;
} }
cbq_update_toplevel(q, this, q->tx_borrowed); cbq_update_toplevel(q, this, q->tx_borrowed);
@ -943,31 +943,13 @@ cbq_dequeue(struct Qdisc *sch)
struct sk_buff *skb; struct sk_buff *skb;
struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_sched_data *q = qdisc_priv(sch);
psched_time_t now; psched_time_t now;
psched_tdiff_t incr;
now = psched_get_time(); now = psched_get_time();
incr = now - q->now_rt;
if (q->tx_class) { if (q->tx_class)
psched_tdiff_t incr2;
/* Time integrator. We calculate EOS time
* by adding expected packet transmission time.
* If real time is greater, we warp artificial clock,
* so that:
*
* cbq_time = max(real_time, work);
*/
incr2 = L2T(&q->link, q->tx_len);
q->now += incr2;
cbq_update(q); cbq_update(q);
if ((incr -= incr2) < 0)
incr = 0; q->now = now;
q->now += incr;
} else {
if (now > q->now)
q->now = now;
}
q->now_rt = now;
for (;;) { for (;;) {
q->wd_expires = 0; q->wd_expires = 0;
@ -1223,7 +1205,6 @@ cbq_reset(struct Qdisc *sch)
hrtimer_cancel(&q->delay_timer); hrtimer_cancel(&q->delay_timer);
q->toplevel = TC_CBQ_MAXLEVEL; q->toplevel = TC_CBQ_MAXLEVEL;
q->now = psched_get_time(); q->now = psched_get_time();
q->now_rt = q->now;
for (prio = 0; prio <= TC_CBQ_MAXPRIO; prio++) for (prio = 0; prio <= TC_CBQ_MAXPRIO; prio++)
q->active[prio] = NULL; q->active[prio] = NULL;
@ -1407,7 +1388,6 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
q->delay_timer.function = cbq_undelay; q->delay_timer.function = cbq_undelay;
q->toplevel = TC_CBQ_MAXLEVEL; q->toplevel = TC_CBQ_MAXLEVEL;
q->now = psched_get_time(); q->now = psched_get_time();
q->now_rt = q->now;
cbq_link_class(&q->link); cbq_link_class(&q->link);

View File

@ -813,6 +813,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
else { else {
dst_release(transport->dst); dst_release(transport->dst);
transport->dst = NULL; transport->dst = NULL;
ulp_notify = false;
} }
spc_state = SCTP_ADDR_UNREACHABLE; spc_state = SCTP_ADDR_UNREACHABLE;
@ -1244,7 +1245,7 @@ static struct sctp_transport *sctp_trans_elect_best(struct sctp_transport *curr,
{ {
u8 score_curr, score_best; u8 score_curr, score_best;
if (best == NULL) if (best == NULL || curr == best)
return curr; return curr;
score_curr = sctp_trans_score(curr); score_curr = sctp_trans_score(curr);
@ -1355,14 +1356,11 @@ static void sctp_select_active_and_retran_path(struct sctp_association *asoc)
trans_sec = trans_pri; trans_sec = trans_pri;
/* If we failed to find a usable transport, just camp on the /* If we failed to find a usable transport, just camp on the
* primary or retran, even if they are inactive, if possible * active or pick a PF iff it's the better choice.
* pick a PF iff it's the better choice.
*/ */
if (trans_pri == NULL) { if (trans_pri == NULL) {
trans_pri = sctp_trans_elect_best(asoc->peer.primary_path, trans_pri = sctp_trans_elect_best(asoc->peer.active_path, trans_pf);
asoc->peer.retran_path); trans_sec = trans_pri;
trans_pri = sctp_trans_elect_best(trans_pri, trans_pf);
trans_sec = asoc->peer.primary_path;
} }
/* Set the active and retran transports. */ /* Set the active and retran transports. */

View File

@ -179,9 +179,12 @@ static inline int tipc_port_importance(struct tipc_port *port)
return msg_importance(&port->phdr); return msg_importance(&port->phdr);
} }
static inline void tipc_port_set_importance(struct tipc_port *port, int imp) static inline int tipc_port_set_importance(struct tipc_port *port, int imp)
{ {
if (imp > TIPC_CRITICAL_IMPORTANCE)
return -EINVAL;
msg_set_importance(&port->phdr, (u32)imp); msg_set_importance(&port->phdr, (u32)imp);
return 0;
} }
#endif #endif

View File

@ -1973,7 +1973,7 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt,
switch (opt) { switch (opt) {
case TIPC_IMPORTANCE: case TIPC_IMPORTANCE:
tipc_port_set_importance(port, value); res = tipc_port_set_importance(port, value);
break; break;
case TIPC_SRC_DROPPABLE: case TIPC_SRC_DROPPABLE:
if (sock->type != SOCK_STREAM) if (sock->type != SOCK_STREAM)