mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'net-6.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Jakub Kicinski:
"Including fixes from BPF, netfilter, bluetooth and CAN.
Current release - regressions:
- eth: r8169: multiple fixes for PCIe ASPM-related problems
- vrf: fix RCU lockdep splat in output path
Previous releases - regressions:
- gso: fall back to SW segmenting with GSO_UDP_L4 dodgy bit set
- dsa: mv88e6xxx: do a final check before timing out when polling
- nf_tables: fix sleep in atomic in nft_chain_validate
Previous releases - always broken:
- sched: fix undoing tcf_bind_filter() in multiple classifiers
- bpf, arm64: fix BTI type used for freplace attached functions
- can: gs_usb: fix time stamp counter initialization
- nft_set_pipapo: fix improper element removal (leading to UAF)
Misc:
- net: support STP on bridge in non-root netns, STP prevents packet
loops so not supporting it results in freezing systems of
unsuspecting users, and in turn very upset noises being made
- fix kdoc warnings
- annotate various bits of TCP state to prevent data races"
* tag 'net-6.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (95 commits)
net: phy: prevent stale pointer dereference in phy_init()
tcp: annotate data-races around fastopenq.max_qlen
tcp: annotate data-races around icsk->icsk_user_timeout
tcp: annotate data-races around tp->notsent_lowat
tcp: annotate data-races around rskq_defer_accept
tcp: annotate data-races around tp->linger2
tcp: annotate data-races around icsk->icsk_syn_retries
tcp: annotate data-races around tp->keepalive_probes
tcp: annotate data-races around tp->keepalive_intvl
tcp: annotate data-races around tp->keepalive_time
tcp: annotate data-races around tp->tsoffset
tcp: annotate data-races around tp->tcp_tx_delay
Bluetooth: MGMT: Use correct address for memcpy()
Bluetooth: btusb: Fix bluetooth on Intel Macbook 2014
Bluetooth: SCO: fix sco_conn related locking and validity issues
Bluetooth: hci_conn: return ERR_PTR instead of NULL when there is no link
Bluetooth: hci_sync: Avoid use-after-free in dbg for hci_remove_adv_monitor()
Bluetooth: coredump: fix building with coredump disabled
Bluetooth: ISO: fix iso_conn related locking and validity issues
Bluetooth: hci_event: call disconnect callback before deleting conn
...
This commit is contained in:
3
.mailmap
3
.mailmap
@@ -241,6 +241,7 @@ Jisheng Zhang <jszhang@kernel.org> <Jisheng.Zhang@synaptics.com>
|
||||
Johan Hovold <johan@kernel.org> <jhovold@gmail.com>
|
||||
Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
|
||||
John Crispin <john@phrozen.org> <blogic@openwrt.org>
|
||||
John Fastabend <john.fastabend@gmail.com> <john.r.fastabend@intel.com>
|
||||
John Keeping <john@keeping.me.uk> <john@metanate.com>
|
||||
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
|
||||
John Stultz <johnstul@us.ibm.com>
|
||||
@@ -454,6 +455,8 @@ Sebastian Reichel <sre@kernel.org> <sre@debian.org>
|
||||
Sedat Dilek <sedat.dilek@gmail.com> <sedat.dilek@credativ.de>
|
||||
Seth Forshee <sforshee@kernel.org> <seth.forshee@canonical.com>
|
||||
Shannon Nelson <shannon.nelson@amd.com> <snelson@pensando.io>
|
||||
Shannon Nelson <shannon.nelson@amd.com> <shannon.nelson@intel.com>
|
||||
Shannon Nelson <shannon.nelson@amd.com> <shannon.nelson@oracle.com>
|
||||
Shiraz Hashim <shiraz.linux.kernel@gmail.com> <shiraz.hashim@st.com>
|
||||
Shuah Khan <shuah@kernel.org> <shuahkhan@gmail.com>
|
||||
Shuah Khan <shuah@kernel.org> <shuah.khan@hp.com>
|
||||
|
||||
@@ -322,7 +322,13 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
|
||||
*
|
||||
*/
|
||||
|
||||
emit_bti(A64_BTI_C, ctx);
|
||||
/* bpf function may be invoked by 3 instruction types:
|
||||
* 1. bl, attached via freplace to bpf prog via short jump
|
||||
* 2. br, attached via freplace to bpf prog via long jump
|
||||
* 3. blr, working as a function pointer, used by emit_call.
|
||||
* So BTI_JC should used here to support both br and blr.
|
||||
*/
|
||||
emit_bti(A64_BTI_JC, ctx);
|
||||
|
||||
emit(A64_MOV(1, A64_R(9), A64_LR), ctx);
|
||||
emit(A64_NOP, ctx);
|
||||
|
||||
@@ -4104,6 +4104,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
BT_DBG("intf %p id %p", intf, id);
|
||||
|
||||
if ((id->driver_info & BTUSB_IFNUM_2) &&
|
||||
(intf->cur_altsetting->desc.bInterfaceNumber != 0) &&
|
||||
(intf->cur_altsetting->desc.bInterfaceNumber != 2))
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
@@ -227,6 +227,8 @@ static int
|
||||
__mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
|
||||
const u8 mode_req, bool nowait)
|
||||
{
|
||||
const struct can_bittiming *bt = &priv->can.bittiming;
|
||||
unsigned long timeout_us = MCP251XFD_POLL_TIMEOUT_US;
|
||||
u32 con = 0, con_reqop, osc = 0;
|
||||
u8 mode;
|
||||
int err;
|
||||
@@ -246,12 +248,16 @@ __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
|
||||
if (mode_req == MCP251XFD_REG_CON_MODE_SLEEP || nowait)
|
||||
return 0;
|
||||
|
||||
if (bt->bitrate)
|
||||
timeout_us = max_t(unsigned long, timeout_us,
|
||||
MCP251XFD_FRAME_LEN_MAX_BITS * USEC_PER_SEC /
|
||||
bt->bitrate);
|
||||
|
||||
err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_CON, con,
|
||||
!mcp251xfd_reg_invalid(con) &&
|
||||
FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK,
|
||||
con) == mode_req,
|
||||
MCP251XFD_POLL_SLEEP_US,
|
||||
MCP251XFD_POLL_TIMEOUT_US);
|
||||
MCP251XFD_POLL_SLEEP_US, timeout_us);
|
||||
if (err != -ETIMEDOUT && err != -EBADMSG)
|
||||
return err;
|
||||
|
||||
|
||||
@@ -387,6 +387,7 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
|
||||
#define MCP251XFD_OSC_STAB_TIMEOUT_US (10 * MCP251XFD_OSC_STAB_SLEEP_US)
|
||||
#define MCP251XFD_POLL_SLEEP_US (10)
|
||||
#define MCP251XFD_POLL_TIMEOUT_US (USEC_PER_MSEC)
|
||||
#define MCP251XFD_FRAME_LEN_MAX_BITS (736)
|
||||
|
||||
/* Misc */
|
||||
#define MCP251XFD_NAPI_WEIGHT 32
|
||||
|
||||
@@ -303,12 +303,6 @@ struct gs_can {
|
||||
struct can_bittiming_const bt_const, data_bt_const;
|
||||
unsigned int channel; /* channel number */
|
||||
|
||||
/* time counter for hardware timestamps */
|
||||
struct cyclecounter cc;
|
||||
struct timecounter tc;
|
||||
spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
|
||||
struct delayed_work timestamp;
|
||||
|
||||
u32 feature;
|
||||
unsigned int hf_size_tx;
|
||||
|
||||
@@ -325,6 +319,13 @@ struct gs_usb {
|
||||
struct gs_can *canch[GS_MAX_INTF];
|
||||
struct usb_anchor rx_submitted;
|
||||
struct usb_device *udev;
|
||||
|
||||
/* time counter for hardware timestamps */
|
||||
struct cyclecounter cc;
|
||||
struct timecounter tc;
|
||||
spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
|
||||
struct delayed_work timestamp;
|
||||
|
||||
unsigned int hf_size_rx;
|
||||
u8 active_channels;
|
||||
};
|
||||
@@ -388,15 +389,15 @@ static int gs_cmd_reset(struct gs_can *dev)
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
static inline int gs_usb_get_timestamp(const struct gs_can *dev,
|
||||
static inline int gs_usb_get_timestamp(const struct gs_usb *parent,
|
||||
u32 *timestamp_p)
|
||||
{
|
||||
__le32 timestamp;
|
||||
int rc;
|
||||
|
||||
rc = usb_control_msg_recv(dev->udev, 0, GS_USB_BREQ_TIMESTAMP,
|
||||
rc = usb_control_msg_recv(parent->udev, 0, GS_USB_BREQ_TIMESTAMP,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||
dev->channel, 0,
|
||||
0, 0,
|
||||
×tamp, sizeof(timestamp),
|
||||
USB_CTRL_GET_TIMEOUT,
|
||||
GFP_KERNEL);
|
||||
@@ -410,20 +411,20 @@ static inline int gs_usb_get_timestamp(const struct gs_can *dev,
|
||||
|
||||
static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev->tc_lock)
|
||||
{
|
||||
struct gs_can *dev = container_of(cc, struct gs_can, cc);
|
||||
struct gs_usb *parent = container_of(cc, struct gs_usb, cc);
|
||||
u32 timestamp = 0;
|
||||
int err;
|
||||
|
||||
lockdep_assert_held(&dev->tc_lock);
|
||||
lockdep_assert_held(&parent->tc_lock);
|
||||
|
||||
/* drop lock for synchronous USB transfer */
|
||||
spin_unlock_bh(&dev->tc_lock);
|
||||
err = gs_usb_get_timestamp(dev, ×tamp);
|
||||
spin_lock_bh(&dev->tc_lock);
|
||||
spin_unlock_bh(&parent->tc_lock);
|
||||
err = gs_usb_get_timestamp(parent, ×tamp);
|
||||
spin_lock_bh(&parent->tc_lock);
|
||||
if (err)
|
||||
netdev_err(dev->netdev,
|
||||
"Error %d while reading timestamp. HW timestamps may be inaccurate.",
|
||||
err);
|
||||
dev_err(&parent->udev->dev,
|
||||
"Error %d while reading timestamp. HW timestamps may be inaccurate.",
|
||||
err);
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
@@ -431,14 +432,14 @@ static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev
|
||||
static void gs_usb_timestamp_work(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work = to_delayed_work(work);
|
||||
struct gs_can *dev;
|
||||
struct gs_usb *parent;
|
||||
|
||||
dev = container_of(delayed_work, struct gs_can, timestamp);
|
||||
spin_lock_bh(&dev->tc_lock);
|
||||
timecounter_read(&dev->tc);
|
||||
spin_unlock_bh(&dev->tc_lock);
|
||||
parent = container_of(delayed_work, struct gs_usb, timestamp);
|
||||
spin_lock_bh(&parent->tc_lock);
|
||||
timecounter_read(&parent->tc);
|
||||
spin_unlock_bh(&parent->tc_lock);
|
||||
|
||||
schedule_delayed_work(&dev->timestamp,
|
||||
schedule_delayed_work(&parent->timestamp,
|
||||
GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
|
||||
}
|
||||
|
||||
@@ -446,37 +447,38 @@ static void gs_usb_skb_set_timestamp(struct gs_can *dev,
|
||||
struct sk_buff *skb, u32 timestamp)
|
||||
{
|
||||
struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
|
||||
struct gs_usb *parent = dev->parent;
|
||||
u64 ns;
|
||||
|
||||
spin_lock_bh(&dev->tc_lock);
|
||||
ns = timecounter_cyc2time(&dev->tc, timestamp);
|
||||
spin_unlock_bh(&dev->tc_lock);
|
||||
spin_lock_bh(&parent->tc_lock);
|
||||
ns = timecounter_cyc2time(&parent->tc, timestamp);
|
||||
spin_unlock_bh(&parent->tc_lock);
|
||||
|
||||
hwtstamps->hwtstamp = ns_to_ktime(ns);
|
||||
}
|
||||
|
||||
static void gs_usb_timestamp_init(struct gs_can *dev)
|
||||
static void gs_usb_timestamp_init(struct gs_usb *parent)
|
||||
{
|
||||
struct cyclecounter *cc = &dev->cc;
|
||||
struct cyclecounter *cc = &parent->cc;
|
||||
|
||||
cc->read = gs_usb_timestamp_read;
|
||||
cc->mask = CYCLECOUNTER_MASK(32);
|
||||
cc->shift = 32 - bits_per(NSEC_PER_SEC / GS_USB_TIMESTAMP_TIMER_HZ);
|
||||
cc->mult = clocksource_hz2mult(GS_USB_TIMESTAMP_TIMER_HZ, cc->shift);
|
||||
|
||||
spin_lock_init(&dev->tc_lock);
|
||||
spin_lock_bh(&dev->tc_lock);
|
||||
timecounter_init(&dev->tc, &dev->cc, ktime_get_real_ns());
|
||||
spin_unlock_bh(&dev->tc_lock);
|
||||
spin_lock_init(&parent->tc_lock);
|
||||
spin_lock_bh(&parent->tc_lock);
|
||||
timecounter_init(&parent->tc, &parent->cc, ktime_get_real_ns());
|
||||
spin_unlock_bh(&parent->tc_lock);
|
||||
|
||||
INIT_DELAYED_WORK(&dev->timestamp, gs_usb_timestamp_work);
|
||||
schedule_delayed_work(&dev->timestamp,
|
||||
INIT_DELAYED_WORK(&parent->timestamp, gs_usb_timestamp_work);
|
||||
schedule_delayed_work(&parent->timestamp,
|
||||
GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
|
||||
}
|
||||
|
||||
static void gs_usb_timestamp_stop(struct gs_can *dev)
|
||||
static void gs_usb_timestamp_stop(struct gs_usb *parent)
|
||||
{
|
||||
cancel_delayed_work_sync(&dev->timestamp);
|
||||
cancel_delayed_work_sync(&parent->timestamp);
|
||||
}
|
||||
|
||||
static void gs_update_state(struct gs_can *dev, struct can_frame *cf)
|
||||
@@ -560,6 +562,9 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
|
||||
if (!netif_device_present(netdev))
|
||||
return;
|
||||
|
||||
if (!netif_running(netdev))
|
||||
goto resubmit_urb;
|
||||
|
||||
if (hf->echo_id == -1) { /* normal rx */
|
||||
if (hf->flags & GS_CAN_FLAG_FD) {
|
||||
skb = alloc_canfd_skb(dev->netdev, &cfd);
|
||||
@@ -833,6 +838,7 @@ static int gs_can_open(struct net_device *netdev)
|
||||
.mode = cpu_to_le32(GS_CAN_MODE_START),
|
||||
};
|
||||
struct gs_host_frame *hf;
|
||||
struct urb *urb = NULL;
|
||||
u32 ctrlmode;
|
||||
u32 flags = 0;
|
||||
int rc, i;
|
||||
@@ -855,14 +861,18 @@ static int gs_can_open(struct net_device *netdev)
|
||||
}
|
||||
|
||||
if (!parent->active_channels) {
|
||||
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
|
||||
gs_usb_timestamp_init(parent);
|
||||
|
||||
for (i = 0; i < GS_MAX_RX_URBS; i++) {
|
||||
struct urb *urb;
|
||||
u8 *buf;
|
||||
|
||||
/* alloc rx urb */
|
||||
urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
if (!urb) {
|
||||
rc = -ENOMEM;
|
||||
goto out_usb_kill_anchored_urbs;
|
||||
}
|
||||
|
||||
/* alloc rx buffer */
|
||||
buf = kmalloc(dev->parent->hf_size_rx,
|
||||
@@ -870,8 +880,8 @@ static int gs_can_open(struct net_device *netdev)
|
||||
if (!buf) {
|
||||
netdev_err(netdev,
|
||||
"No memory left for USB buffer\n");
|
||||
usb_free_urb(urb);
|
||||
return -ENOMEM;
|
||||
rc = -ENOMEM;
|
||||
goto out_usb_free_urb;
|
||||
}
|
||||
|
||||
/* fill, anchor, and submit rx urb */
|
||||
@@ -894,9 +904,7 @@ static int gs_can_open(struct net_device *netdev)
|
||||
netdev_err(netdev,
|
||||
"usb_submit failed (err=%d)\n", rc);
|
||||
|
||||
usb_unanchor_urb(urb);
|
||||
usb_free_urb(urb);
|
||||
break;
|
||||
goto out_usb_unanchor_urb;
|
||||
}
|
||||
|
||||
/* Drop reference,
|
||||
@@ -926,13 +934,9 @@ static int gs_can_open(struct net_device *netdev)
|
||||
flags |= GS_CAN_MODE_FD;
|
||||
|
||||
/* if hardware supports timestamps, enable it */
|
||||
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) {
|
||||
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
|
||||
flags |= GS_CAN_MODE_HW_TIMESTAMP;
|
||||
|
||||
/* start polling timestamp */
|
||||
gs_usb_timestamp_init(dev);
|
||||
}
|
||||
|
||||
/* finally start device */
|
||||
dev->can.state = CAN_STATE_ERROR_ACTIVE;
|
||||
dm.flags = cpu_to_le32(flags);
|
||||
@@ -942,10 +946,9 @@ static int gs_can_open(struct net_device *netdev)
|
||||
GFP_KERNEL);
|
||||
if (rc) {
|
||||
netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
|
||||
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
|
||||
gs_usb_timestamp_stop(dev);
|
||||
dev->can.state = CAN_STATE_STOPPED;
|
||||
return rc;
|
||||
|
||||
goto out_usb_kill_anchored_urbs;
|
||||
}
|
||||
|
||||
parent->active_channels++;
|
||||
@@ -953,6 +956,22 @@ static int gs_can_open(struct net_device *netdev)
|
||||
netif_start_queue(netdev);
|
||||
|
||||
return 0;
|
||||
|
||||
out_usb_unanchor_urb:
|
||||
usb_unanchor_urb(urb);
|
||||
out_usb_free_urb:
|
||||
usb_free_urb(urb);
|
||||
out_usb_kill_anchored_urbs:
|
||||
if (!parent->active_channels) {
|
||||
usb_kill_anchored_urbs(&dev->tx_submitted);
|
||||
|
||||
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
|
||||
gs_usb_timestamp_stop(parent);
|
||||
}
|
||||
|
||||
close_candev(netdev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int gs_usb_get_state(const struct net_device *netdev,
|
||||
@@ -998,14 +1017,13 @@ static int gs_can_close(struct net_device *netdev)
|
||||
|
||||
netif_stop_queue(netdev);
|
||||
|
||||
/* stop polling timestamp */
|
||||
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
|
||||
gs_usb_timestamp_stop(dev);
|
||||
|
||||
/* Stop polling */
|
||||
parent->active_channels--;
|
||||
if (!parent->active_channels) {
|
||||
usb_kill_anchored_urbs(&parent->rx_submitted);
|
||||
|
||||
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
|
||||
gs_usb_timestamp_stop(parent);
|
||||
}
|
||||
|
||||
/* Stop sending URBs */
|
||||
|
||||
@@ -506,7 +506,13 @@ static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
|
||||
(data_hi & masks[STATIC_MAC_TABLE_FWD_PORTS]) >>
|
||||
shifts[STATIC_MAC_FWD_PORTS];
|
||||
alu->is_override = (data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0;
|
||||
data_hi >>= 1;
|
||||
|
||||
/* KSZ8795 family switches have STATIC_MAC_TABLE_USE_FID and
|
||||
* STATIC_MAC_TABLE_FID definitions off by 1 when doing read on the
|
||||
* static MAC table compared to doing write.
|
||||
*/
|
||||
if (ksz_is_ksz87xx(dev))
|
||||
data_hi >>= 1;
|
||||
alu->is_static = true;
|
||||
alu->is_use_fid = (data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0;
|
||||
alu->fid = (data_hi & masks[STATIC_MAC_TABLE_FID]) >>
|
||||
|
||||
@@ -331,13 +331,13 @@ static const u32 ksz8795_masks[] = {
|
||||
[STATIC_MAC_TABLE_VALID] = BIT(21),
|
||||
[STATIC_MAC_TABLE_USE_FID] = BIT(23),
|
||||
[STATIC_MAC_TABLE_FID] = GENMASK(30, 24),
|
||||
[STATIC_MAC_TABLE_OVERRIDE] = BIT(26),
|
||||
[STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(24, 20),
|
||||
[STATIC_MAC_TABLE_OVERRIDE] = BIT(22),
|
||||
[STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(20, 16),
|
||||
[DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(6, 0),
|
||||
[DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(8),
|
||||
[DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(7),
|
||||
[DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7),
|
||||
[DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 29),
|
||||
[DYNAMIC_MAC_TABLE_FID] = GENMASK(26, 20),
|
||||
[DYNAMIC_MAC_TABLE_FID] = GENMASK(22, 16),
|
||||
[DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24),
|
||||
[DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27),
|
||||
[P_MII_TX_FLOW_CTRL] = BIT(5),
|
||||
|
||||
@@ -601,6 +601,13 @@ static inline void ksz_regmap_unlock(void *__mtx)
|
||||
mutex_unlock(mtx);
|
||||
}
|
||||
|
||||
static inline bool ksz_is_ksz87xx(struct ksz_device *dev)
|
||||
{
|
||||
return dev->chip_id == KSZ8795_CHIP_ID ||
|
||||
dev->chip_id == KSZ8794_CHIP_ID ||
|
||||
dev->chip_id == KSZ8765_CHIP_ID;
|
||||
}
|
||||
|
||||
static inline bool ksz_is_ksz88x3(struct ksz_device *dev)
|
||||
{
|
||||
return dev->chip_id == KSZ8830_CHIP_ID;
|
||||
|
||||
@@ -109,6 +109,13 @@ int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
|
||||
err = mv88e6xxx_read(chip, addr, reg, &data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((data & mask) == val)
|
||||
return 0;
|
||||
|
||||
dev_err(chip->dev, "Timeout while waiting for switch\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@@ -1002,6 +1002,8 @@ static const struct regmap_config ar9331_mdio_regmap_config = {
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.max_register = AR9331_SW_REG_PAGE,
|
||||
.use_single_read = true,
|
||||
.use_single_write = true,
|
||||
|
||||
.ranges = ar9331_regmap_range,
|
||||
.num_ranges = ARRAY_SIZE(ar9331_regmap_range),
|
||||
@@ -1018,8 +1020,6 @@ static struct regmap_bus ar9331_sw_bus = {
|
||||
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
||||
.read = ar9331_mdio_read,
|
||||
.write = ar9331_sw_bus_write,
|
||||
.max_raw_read = 4,
|
||||
.max_raw_write = 4,
|
||||
};
|
||||
|
||||
static int ar9331_sw_probe(struct mdio_device *mdiodev)
|
||||
|
||||
@@ -512,11 +512,6 @@ bnad_debugfs_init(struct bnad *bnad)
|
||||
if (!bnad->port_debugfs_root) {
|
||||
bnad->port_debugfs_root =
|
||||
debugfs_create_dir(name, bna_debugfs_root);
|
||||
if (!bnad->port_debugfs_root) {
|
||||
netdev_warn(bnad->netdev,
|
||||
"debugfs root dir creation failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
atomic_inc(&bna_debugfs_port_count);
|
||||
|
||||
|
||||
@@ -255,8 +255,10 @@ struct iavf_adapter {
|
||||
struct workqueue_struct *wq;
|
||||
struct work_struct reset_task;
|
||||
struct work_struct adminq_task;
|
||||
struct work_struct finish_config;
|
||||
struct delayed_work client_task;
|
||||
wait_queue_head_t down_waitqueue;
|
||||
wait_queue_head_t reset_waitqueue;
|
||||
wait_queue_head_t vc_waitqueue;
|
||||
struct iavf_q_vector *q_vectors;
|
||||
struct list_head vlan_filter_list;
|
||||
@@ -518,8 +520,9 @@ int iavf_up(struct iavf_adapter *adapter);
|
||||
void iavf_down(struct iavf_adapter *adapter);
|
||||
int iavf_process_config(struct iavf_adapter *adapter);
|
||||
int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter);
|
||||
void iavf_schedule_reset(struct iavf_adapter *adapter);
|
||||
void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags);
|
||||
void iavf_schedule_request_stats(struct iavf_adapter *adapter);
|
||||
void iavf_schedule_finish_config(struct iavf_adapter *adapter);
|
||||
void iavf_reset(struct iavf_adapter *adapter);
|
||||
void iavf_set_ethtool_ops(struct net_device *netdev);
|
||||
void iavf_update_stats(struct iavf_adapter *adapter);
|
||||
@@ -582,4 +585,5 @@ void iavf_add_adv_rss_cfg(struct iavf_adapter *adapter);
|
||||
void iavf_del_adv_rss_cfg(struct iavf_adapter *adapter);
|
||||
struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
|
||||
const u8 *macaddr);
|
||||
int iavf_wait_for_reset(struct iavf_adapter *adapter);
|
||||
#endif /* _IAVF_H_ */
|
||||
|
||||
@@ -484,6 +484,7 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
|
||||
{
|
||||
struct iavf_adapter *adapter = netdev_priv(netdev);
|
||||
u32 orig_flags, new_flags, changed_flags;
|
||||
int ret = 0;
|
||||
u32 i;
|
||||
|
||||
orig_flags = READ_ONCE(adapter->flags);
|
||||
@@ -531,12 +532,14 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
|
||||
/* issue a reset to force legacy-rx change to take effect */
|
||||
if (changed_flags & IAVF_FLAG_LEGACY_RX) {
|
||||
if (netif_running(netdev)) {
|
||||
adapter->flags |= IAVF_FLAG_RESET_NEEDED;
|
||||
queue_work(adapter->wq, &adapter->reset_task);
|
||||
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
|
||||
ret = iavf_wait_for_reset(adapter);
|
||||
if (ret)
|
||||
netdev_warn(netdev, "Changing private flags timeout or interrupted waiting for reset");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -627,6 +630,7 @@ static int iavf_set_ringparam(struct net_device *netdev,
|
||||
{
|
||||
struct iavf_adapter *adapter = netdev_priv(netdev);
|
||||
u32 new_rx_count, new_tx_count;
|
||||
int ret = 0;
|
||||
|
||||
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
|
||||
return -EINVAL;
|
||||
@@ -671,11 +675,13 @@ static int iavf_set_ringparam(struct net_device *netdev,
|
||||
}
|
||||
|
||||
if (netif_running(netdev)) {
|
||||
adapter->flags |= IAVF_FLAG_RESET_NEEDED;
|
||||
queue_work(adapter->wq, &adapter->reset_task);
|
||||
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
|
||||
ret = iavf_wait_for_reset(adapter);
|
||||
if (ret)
|
||||
netdev_warn(netdev, "Changing ring parameters timeout or interrupted waiting for reset");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1830,7 +1836,7 @@ static int iavf_set_channels(struct net_device *netdev,
|
||||
{
|
||||
struct iavf_adapter *adapter = netdev_priv(netdev);
|
||||
u32 num_req = ch->combined_count;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
|
||||
adapter->num_tc) {
|
||||
@@ -1852,22 +1858,13 @@ static int iavf_set_channels(struct net_device *netdev,
|
||||
|
||||
adapter->num_req_queues = num_req;
|
||||
adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED;
|
||||
iavf_schedule_reset(adapter);
|
||||
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
|
||||
|
||||
/* wait for the reset is done */
|
||||
for (i = 0; i < IAVF_RESET_WAIT_COMPLETE_COUNT; i++) {
|
||||
msleep(IAVF_RESET_WAIT_MS);
|
||||
if (adapter->flags & IAVF_FLAG_RESET_PENDING)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) {
|
||||
adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
|
||||
adapter->num_active_queues = num_req;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
ret = iavf_wait_for_reset(adapter);
|
||||
if (ret)
|
||||
netdev_warn(netdev, "Changing channel count timeout or interrupted waiting for reset");
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -166,6 +166,45 @@ static struct iavf_adapter *iavf_pdev_to_adapter(struct pci_dev *pdev)
|
||||
return netdev_priv(pci_get_drvdata(pdev));
|
||||
}
|
||||
|
||||
/**
|
||||
* iavf_is_reset_in_progress - Check if a reset is in progress
|
||||
* @adapter: board private structure
|
||||
*/
|
||||
static bool iavf_is_reset_in_progress(struct iavf_adapter *adapter)
|
||||
{
|
||||
if (adapter->state == __IAVF_RESETTING ||
|
||||
adapter->flags & (IAVF_FLAG_RESET_PENDING |
|
||||
IAVF_FLAG_RESET_NEEDED))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* iavf_wait_for_reset - Wait for reset to finish.
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Returns 0 if reset finished successfully, negative on timeout or interrupt.
|
||||
*/
|
||||
int iavf_wait_for_reset(struct iavf_adapter *adapter)
|
||||
{
|
||||
int ret = wait_event_interruptible_timeout(adapter->reset_waitqueue,
|
||||
!iavf_is_reset_in_progress(adapter),
|
||||
msecs_to_jiffies(5000));
|
||||
|
||||
/* If ret < 0 then it means wait was interrupted.
|
||||
* If ret == 0 then it means we got a timeout while waiting
|
||||
* for reset to finish.
|
||||
* If ret > 0 it means reset has finished.
|
||||
*/
|
||||
if (ret > 0)
|
||||
return 0;
|
||||
else if (ret < 0)
|
||||
return -EINTR;
|
||||
else
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/**
|
||||
* iavf_allocate_dma_mem_d - OS specific memory alloc for shared code
|
||||
* @hw: pointer to the HW structure
|
||||
@@ -262,12 +301,14 @@ static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
|
||||
/**
|
||||
* iavf_schedule_reset - Set the flags and schedule a reset event
|
||||
* @adapter: board private structure
|
||||
* @flags: IAVF_FLAG_RESET_PENDING or IAVF_FLAG_RESET_NEEDED
|
||||
**/
|
||||
void iavf_schedule_reset(struct iavf_adapter *adapter)
|
||||
void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags)
|
||||
{
|
||||
if (!(adapter->flags &
|
||||
(IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
|
||||
adapter->flags |= IAVF_FLAG_RESET_NEEDED;
|
||||
if (!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
|
||||
!(adapter->flags &
|
||||
(IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
|
||||
adapter->flags |= flags;
|
||||
queue_work(adapter->wq, &adapter->reset_task);
|
||||
}
|
||||
}
|
||||
@@ -295,7 +336,7 @@ static void iavf_tx_timeout(struct net_device *netdev, unsigned int txqueue)
|
||||
struct iavf_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
adapter->tx_timeout_count++;
|
||||
iavf_schedule_reset(adapter);
|
||||
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1651,10 +1692,10 @@ static int iavf_set_interrupt_capability(struct iavf_adapter *adapter)
|
||||
adapter->msix_entries[vector].entry = vector;
|
||||
|
||||
err = iavf_acquire_msix_vectors(adapter, v_budget);
|
||||
if (!err)
|
||||
iavf_schedule_finish_config(adapter);
|
||||
|
||||
out:
|
||||
netif_set_real_num_rx_queues(adapter->netdev, pairs);
|
||||
netif_set_real_num_tx_queues(adapter->netdev, pairs);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1828,19 +1869,16 @@ static int iavf_alloc_q_vectors(struct iavf_adapter *adapter)
|
||||
static void iavf_free_q_vectors(struct iavf_adapter *adapter)
|
||||
{
|
||||
int q_idx, num_q_vectors;
|
||||
int napi_vectors;
|
||||
|
||||
if (!adapter->q_vectors)
|
||||
return;
|
||||
|
||||
num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
|
||||
napi_vectors = adapter->num_active_queues;
|
||||
|
||||
for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
|
||||
struct iavf_q_vector *q_vector = &adapter->q_vectors[q_idx];
|
||||
|
||||
if (q_idx < napi_vectors)
|
||||
netif_napi_del(&q_vector->napi);
|
||||
netif_napi_del(&q_vector->napi);
|
||||
}
|
||||
kfree(adapter->q_vectors);
|
||||
adapter->q_vectors = NULL;
|
||||
@@ -1877,9 +1915,7 @@ static int iavf_init_interrupt_scheme(struct iavf_adapter *adapter)
|
||||
goto err_alloc_queues;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
err = iavf_set_interrupt_capability(adapter);
|
||||
rtnl_unlock();
|
||||
if (err) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Unable to setup interrupt capabilities\n");
|
||||
@@ -1932,15 +1968,16 @@ static void iavf_free_rss(struct iavf_adapter *adapter)
|
||||
/**
|
||||
* iavf_reinit_interrupt_scheme - Reallocate queues and vectors
|
||||
* @adapter: board private structure
|
||||
* @running: true if adapter->state == __IAVF_RUNNING
|
||||
*
|
||||
* Returns 0 on success, negative on failure
|
||||
**/
|
||||
static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter)
|
||||
static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter, bool running)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
int err;
|
||||
|
||||
if (netif_running(netdev))
|
||||
if (running)
|
||||
iavf_free_traffic_irqs(adapter);
|
||||
iavf_free_misc_irq(adapter);
|
||||
iavf_reset_interrupt_capability(adapter);
|
||||
@@ -1964,6 +2001,78 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* iavf_finish_config - do all netdev work that needs RTNL
|
||||
* @work: our work_struct
|
||||
*
|
||||
* Do work that needs both RTNL and crit_lock.
|
||||
**/
|
||||
static void iavf_finish_config(struct work_struct *work)
|
||||
{
|
||||
struct iavf_adapter *adapter;
|
||||
int pairs, err;
|
||||
|
||||
adapter = container_of(work, struct iavf_adapter, finish_config);
|
||||
|
||||
/* Always take RTNL first to prevent circular lock dependency */
|
||||
rtnl_lock();
|
||||
mutex_lock(&adapter->crit_lock);
|
||||
|
||||
if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
|
||||
adapter->netdev_registered &&
|
||||
!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) {
|
||||
netdev_update_features(adapter->netdev);
|
||||
adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
|
||||
}
|
||||
|
||||
switch (adapter->state) {
|
||||
case __IAVF_DOWN:
|
||||
if (!adapter->netdev_registered) {
|
||||
err = register_netdevice(adapter->netdev);
|
||||
if (err) {
|
||||
dev_err(&adapter->pdev->dev, "Unable to register netdev (%d)\n",
|
||||
err);
|
||||
|
||||
/* go back and try again.*/
|
||||
iavf_free_rss(adapter);
|
||||
iavf_free_misc_irq(adapter);
|
||||
iavf_reset_interrupt_capability(adapter);
|
||||
iavf_change_state(adapter,
|
||||
__IAVF_INIT_CONFIG_ADAPTER);
|
||||
goto out;
|
||||
}
|
||||
adapter->netdev_registered = true;
|
||||
}
|
||||
|
||||
/* Set the real number of queues when reset occurs while
|
||||
* state == __IAVF_DOWN
|
||||
*/
|
||||
fallthrough;
|
||||
case __IAVF_RUNNING:
|
||||
pairs = adapter->num_active_queues;
|
||||
netif_set_real_num_rx_queues(adapter->netdev, pairs);
|
||||
netif_set_real_num_tx_queues(adapter->netdev, pairs);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&adapter->crit_lock);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* iavf_schedule_finish_config - Set the flags and schedule a reset event
|
||||
* @adapter: board private structure
|
||||
**/
|
||||
void iavf_schedule_finish_config(struct iavf_adapter *adapter)
|
||||
{
|
||||
if (!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
|
||||
queue_work(adapter->wq, &adapter->finish_config);
|
||||
}
|
||||
|
||||
/**
|
||||
* iavf_process_aq_command - process aq_required flags
|
||||
* and sends aq command
|
||||
@@ -2371,7 +2480,7 @@ int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter)
|
||||
adapter->vsi_res->num_queue_pairs);
|
||||
adapter->flags |= IAVF_FLAG_REINIT_MSIX_NEEDED;
|
||||
adapter->num_req_queues = adapter->vsi_res->num_queue_pairs;
|
||||
iavf_schedule_reset(adapter);
|
||||
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
@@ -2601,22 +2710,8 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
|
||||
|
||||
netif_carrier_off(netdev);
|
||||
adapter->link_up = false;
|
||||
|
||||
/* set the semaphore to prevent any callbacks after device registration
|
||||
* up to time when state of driver will be set to __IAVF_DOWN
|
||||
*/
|
||||
rtnl_lock();
|
||||
if (!adapter->netdev_registered) {
|
||||
err = register_netdevice(netdev);
|
||||
if (err) {
|
||||
rtnl_unlock();
|
||||
goto err_register;
|
||||
}
|
||||
}
|
||||
|
||||
adapter->netdev_registered = true;
|
||||
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
|
||||
if (CLIENT_ALLOWED(adapter)) {
|
||||
err = iavf_lan_add_device(adapter);
|
||||
if (err)
|
||||
@@ -2629,7 +2724,6 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
|
||||
|
||||
iavf_change_state(adapter, __IAVF_DOWN);
|
||||
set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
|
||||
rtnl_unlock();
|
||||
|
||||
iavf_misc_irq_enable(adapter);
|
||||
wake_up(&adapter->down_waitqueue);
|
||||
@@ -2649,10 +2743,11 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
|
||||
/* request initial VLAN offload settings */
|
||||
iavf_set_vlan_offload_features(adapter, 0, netdev->features);
|
||||
|
||||
iavf_schedule_finish_config(adapter);
|
||||
return;
|
||||
|
||||
err_mem:
|
||||
iavf_free_rss(adapter);
|
||||
err_register:
|
||||
iavf_free_misc_irq(adapter);
|
||||
err_sw_init:
|
||||
iavf_reset_interrupt_capability(adapter);
|
||||
@@ -2679,26 +2774,9 @@ static void iavf_watchdog_task(struct work_struct *work)
|
||||
goto restart_watchdog;
|
||||
}
|
||||
|
||||
if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
|
||||
adapter->netdev_registered &&
|
||||
!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
|
||||
rtnl_trylock()) {
|
||||
netdev_update_features(adapter->netdev);
|
||||
rtnl_unlock();
|
||||
adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
|
||||
}
|
||||
|
||||
if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
|
||||
iavf_change_state(adapter, __IAVF_COMM_FAILED);
|
||||
|
||||
if (adapter->flags & IAVF_FLAG_RESET_NEEDED) {
|
||||
adapter->aq_required = 0;
|
||||
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
|
||||
mutex_unlock(&adapter->crit_lock);
|
||||
queue_work(adapter->wq, &adapter->reset_task);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (adapter->state) {
|
||||
case __IAVF_STARTUP:
|
||||
iavf_startup(adapter);
|
||||
@@ -2826,11 +2904,10 @@ static void iavf_watchdog_task(struct work_struct *work)
|
||||
/* check for hw reset */
|
||||
reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
|
||||
if (!reg_val) {
|
||||
adapter->flags |= IAVF_FLAG_RESET_PENDING;
|
||||
adapter->aq_required = 0;
|
||||
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
|
||||
dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
|
||||
queue_work(adapter->wq, &adapter->reset_task);
|
||||
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
|
||||
mutex_unlock(&adapter->crit_lock);
|
||||
queue_delayed_work(adapter->wq,
|
||||
&adapter->watchdog_task, HZ * 2);
|
||||
@@ -2940,11 +3017,6 @@ static void iavf_reset_task(struct work_struct *work)
|
||||
int i = 0, err;
|
||||
bool running;
|
||||
|
||||
/* Detach interface to avoid subsequent NDO callbacks */
|
||||
rtnl_lock();
|
||||
netif_device_detach(netdev);
|
||||
rtnl_unlock();
|
||||
|
||||
/* When device is being removed it doesn't make sense to run the reset
|
||||
* task, just return in such a case.
|
||||
*/
|
||||
@@ -2952,7 +3024,7 @@ static void iavf_reset_task(struct work_struct *work)
|
||||
if (adapter->state != __IAVF_REMOVE)
|
||||
queue_work(adapter->wq, &adapter->reset_task);
|
||||
|
||||
goto reset_finish;
|
||||
return;
|
||||
}
|
||||
|
||||
while (!mutex_trylock(&adapter->client_lock))
|
||||
@@ -3010,11 +3082,6 @@ static void iavf_reset_task(struct work_struct *work)
|
||||
iavf_disable_vf(adapter);
|
||||
mutex_unlock(&adapter->client_lock);
|
||||
mutex_unlock(&adapter->crit_lock);
|
||||
if (netif_running(netdev)) {
|
||||
rtnl_lock();
|
||||
dev_close(netdev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
return; /* Do not attempt to reinit. It's dead, Jim. */
|
||||
}
|
||||
|
||||
@@ -3056,7 +3123,7 @@ continue_reset:
|
||||
|
||||
if ((adapter->flags & IAVF_FLAG_REINIT_MSIX_NEEDED) ||
|
||||
(adapter->flags & IAVF_FLAG_REINIT_ITR_NEEDED)) {
|
||||
err = iavf_reinit_interrupt_scheme(adapter);
|
||||
err = iavf_reinit_interrupt_scheme(adapter, running);
|
||||
if (err)
|
||||
goto reset_err;
|
||||
}
|
||||
@@ -3151,10 +3218,11 @@ continue_reset:
|
||||
|
||||
adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
|
||||
|
||||
wake_up(&adapter->reset_waitqueue);
|
||||
mutex_unlock(&adapter->client_lock);
|
||||
mutex_unlock(&adapter->crit_lock);
|
||||
|
||||
goto reset_finish;
|
||||
return;
|
||||
reset_err:
|
||||
if (running) {
|
||||
set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
|
||||
@@ -3164,21 +3232,7 @@ reset_err:
|
||||
|
||||
mutex_unlock(&adapter->client_lock);
|
||||
mutex_unlock(&adapter->crit_lock);
|
||||
|
||||
if (netif_running(netdev)) {
|
||||
/* Close device to ensure that Tx queues will not be started
|
||||
* during netif_device_attach() at the end of the reset task.
|
||||
*/
|
||||
rtnl_lock();
|
||||
dev_close(netdev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
|
||||
reset_finish:
|
||||
rtnl_lock();
|
||||
netif_device_attach(netdev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3227,9 +3281,7 @@ static void iavf_adminq_task(struct work_struct *work)
|
||||
} while (pending);
|
||||
mutex_unlock(&adapter->crit_lock);
|
||||
|
||||
if ((adapter->flags &
|
||||
(IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
|
||||
adapter->state == __IAVF_RESETTING)
|
||||
if (iavf_is_reset_in_progress(adapter))
|
||||
goto freedom;
|
||||
|
||||
/* check for error indications */
|
||||
@@ -4315,6 +4367,7 @@ static int iavf_close(struct net_device *netdev)
|
||||
static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
|
||||
{
|
||||
struct iavf_adapter *adapter = netdev_priv(netdev);
|
||||
int ret = 0;
|
||||
|
||||
netdev_dbg(netdev, "changing MTU from %d to %d\n",
|
||||
netdev->mtu, new_mtu);
|
||||
@@ -4325,11 +4378,15 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
|
||||
}
|
||||
|
||||
if (netif_running(netdev)) {
|
||||
adapter->flags |= IAVF_FLAG_RESET_NEEDED;
|
||||
queue_work(adapter->wq, &adapter->reset_task);
|
||||
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
|
||||
ret = iavf_wait_for_reset(adapter);
|
||||
if (ret < 0)
|
||||
netdev_warn(netdev, "MTU change interrupted waiting for reset");
|
||||
else if (ret)
|
||||
netdev_warn(netdev, "MTU change timed out waiting for reset");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define NETIF_VLAN_OFFLOAD_FEATURES (NETIF_F_HW_VLAN_CTAG_RX | \
|
||||
@@ -4922,6 +4979,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
INIT_WORK(&adapter->reset_task, iavf_reset_task);
|
||||
INIT_WORK(&adapter->adminq_task, iavf_adminq_task);
|
||||
INIT_WORK(&adapter->finish_config, iavf_finish_config);
|
||||
INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task);
|
||||
INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task);
|
||||
queue_delayed_work(adapter->wq, &adapter->watchdog_task,
|
||||
@@ -4930,6 +4988,9 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
/* Setup the wait queue for indicating transition to down status */
|
||||
init_waitqueue_head(&adapter->down_waitqueue);
|
||||
|
||||
/* Setup the wait queue for indicating transition to running state */
|
||||
init_waitqueue_head(&adapter->reset_waitqueue);
|
||||
|
||||
/* Setup the wait queue for indicating virtchannel events */
|
||||
init_waitqueue_head(&adapter->vc_waitqueue);
|
||||
|
||||
@@ -5061,13 +5122,15 @@ static void iavf_remove(struct pci_dev *pdev)
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
cancel_delayed_work_sync(&adapter->watchdog_task);
|
||||
cancel_work_sync(&adapter->finish_config);
|
||||
|
||||
rtnl_lock();
|
||||
if (adapter->netdev_registered) {
|
||||
rtnl_lock();
|
||||
unregister_netdevice(netdev);
|
||||
adapter->netdev_registered = false;
|
||||
rtnl_unlock();
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
if (CLIENT_ALLOWED(adapter)) {
|
||||
err = iavf_lan_del_device(adapter);
|
||||
if (err)
|
||||
|
||||
@@ -1961,9 +1961,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
|
||||
case VIRTCHNL_EVENT_RESET_IMPENDING:
|
||||
dev_info(&adapter->pdev->dev, "Reset indication received from the PF\n");
|
||||
if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) {
|
||||
adapter->flags |= IAVF_FLAG_RESET_PENDING;
|
||||
dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
|
||||
queue_work(adapter->wq, &adapter->reset_task);
|
||||
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -2237,6 +2236,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
|
||||
|
||||
iavf_process_config(adapter);
|
||||
adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES;
|
||||
iavf_schedule_finish_config(adapter);
|
||||
|
||||
iavf_set_queue_vlan_tag_loc(adapter);
|
||||
|
||||
@@ -2285,6 +2285,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
|
||||
case VIRTCHNL_OP_ENABLE_QUEUES:
|
||||
/* enable transmits */
|
||||
iavf_irq_enable(adapter, true);
|
||||
wake_up(&adapter->reset_waitqueue);
|
||||
adapter->flags &= ~IAVF_FLAG_QUEUES_DISABLED;
|
||||
break;
|
||||
case VIRTCHNL_OP_DISABLE_QUEUES:
|
||||
|
||||
@@ -800,6 +800,8 @@ void ice_vsi_free_q_vectors(struct ice_vsi *vsi)
|
||||
|
||||
ice_for_each_q_vector(vsi, v_idx)
|
||||
ice_free_q_vector(vsi, v_idx);
|
||||
|
||||
vsi->num_q_vectors = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2681,8 +2681,13 @@ ice_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
|
||||
|
||||
ring->rx_max_pending = ICE_MAX_NUM_DESC;
|
||||
ring->tx_max_pending = ICE_MAX_NUM_DESC;
|
||||
ring->rx_pending = vsi->rx_rings[0]->count;
|
||||
ring->tx_pending = vsi->tx_rings[0]->count;
|
||||
if (vsi->tx_rings && vsi->rx_rings) {
|
||||
ring->rx_pending = vsi->rx_rings[0]->count;
|
||||
ring->tx_pending = vsi->tx_rings[0]->count;
|
||||
} else {
|
||||
ring->rx_pending = 0;
|
||||
ring->tx_pending = 0;
|
||||
}
|
||||
|
||||
/* Rx mini and jumbo rings are not supported */
|
||||
ring->rx_mini_max_pending = 0;
|
||||
@@ -2716,6 +2721,10 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Return if there is no rings (device is reloading) */
|
||||
if (!vsi->tx_rings || !vsi->rx_rings)
|
||||
return -EBUSY;
|
||||
|
||||
new_tx_cnt = ALIGN(ring->tx_pending, ICE_REQ_DESC_MULTIPLE);
|
||||
if (new_tx_cnt != ring->tx_pending)
|
||||
netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n",
|
||||
|
||||
@@ -2972,39 +2972,12 @@ int ice_vsi_release(struct ice_vsi *vsi)
|
||||
return -ENODEV;
|
||||
pf = vsi->back;
|
||||
|
||||
/* do not unregister while driver is in the reset recovery pending
|
||||
* state. Since reset/rebuild happens through PF service task workqueue,
|
||||
* it's not a good idea to unregister netdev that is associated to the
|
||||
* PF that is running the work queue items currently. This is done to
|
||||
* avoid check_flush_dependency() warning on this wq
|
||||
*/
|
||||
if (vsi->netdev && !ice_is_reset_in_progress(pf->state) &&
|
||||
(test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state))) {
|
||||
unregister_netdev(vsi->netdev);
|
||||
clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
|
||||
}
|
||||
|
||||
if (vsi->type == ICE_VSI_PF)
|
||||
ice_devlink_destroy_pf_port(pf);
|
||||
|
||||
if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
|
||||
ice_rss_clean(vsi);
|
||||
|
||||
ice_vsi_close(vsi);
|
||||
ice_vsi_decfg(vsi);
|
||||
|
||||
if (vsi->netdev) {
|
||||
if (test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state)) {
|
||||
unregister_netdev(vsi->netdev);
|
||||
clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
|
||||
}
|
||||
if (test_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state)) {
|
||||
free_netdev(vsi->netdev);
|
||||
vsi->netdev = NULL;
|
||||
clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
|
||||
}
|
||||
}
|
||||
|
||||
/* retain SW VSI data structure since it is needed to unregister and
|
||||
* free VSI netdev when PF is not in reset recovery pending state,\
|
||||
* for ex: during rmmod.
|
||||
|
||||
@@ -4430,9 +4430,9 @@ static int ice_start_eth(struct ice_vsi *vsi)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rtnl_lock();
|
||||
err = ice_vsi_open(vsi);
|
||||
rtnl_unlock();
|
||||
if (err)
|
||||
ice_fltr_remove_all(vsi);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -4895,6 +4895,7 @@ int ice_load(struct ice_pf *pf)
|
||||
params = ice_vsi_to_params(vsi);
|
||||
params.flags = ICE_VSI_FLAG_INIT;
|
||||
|
||||
rtnl_lock();
|
||||
err = ice_vsi_cfg(vsi, ¶ms);
|
||||
if (err)
|
||||
goto err_vsi_cfg;
|
||||
@@ -4902,6 +4903,7 @@ int ice_load(struct ice_pf *pf)
|
||||
err = ice_start_eth(ice_get_main_vsi(pf));
|
||||
if (err)
|
||||
goto err_start_eth;
|
||||
rtnl_unlock();
|
||||
|
||||
err = ice_init_rdma(pf);
|
||||
if (err)
|
||||
@@ -4916,9 +4918,11 @@ int ice_load(struct ice_pf *pf)
|
||||
|
||||
err_init_rdma:
|
||||
ice_vsi_close(ice_get_main_vsi(pf));
|
||||
rtnl_lock();
|
||||
err_start_eth:
|
||||
ice_vsi_decfg(ice_get_main_vsi(pf));
|
||||
err_vsi_cfg:
|
||||
rtnl_unlock();
|
||||
ice_deinit_dev(pf);
|
||||
return err;
|
||||
}
|
||||
@@ -4931,8 +4935,10 @@ void ice_unload(struct ice_pf *pf)
|
||||
{
|
||||
ice_deinit_features(pf);
|
||||
ice_deinit_rdma(pf);
|
||||
rtnl_lock();
|
||||
ice_stop_eth(ice_get_main_vsi(pf));
|
||||
ice_vsi_decfg(ice_get_main_vsi(pf));
|
||||
rtnl_unlock();
|
||||
ice_deinit_dev(pf);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user