diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-16 00:22:29 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-16 00:22:29 +0300 |
commit | d635a69dd4981cc51f90293f5f64268620ed1565 (patch) | |
tree | 5e0a758b402ea7d624c25c3a343545dd29e80f31 /drivers/net/wireless/intersil/orinoco/orinoco_usb.c | |
parent | ac73e3dc8acd0a3be292755db30388c3580f5674 (diff) | |
parent | efd5a1584537698220578227e6467638307c2a0b (diff) | |
download | linux-d635a69dd4981cc51f90293f5f64268620ed1565.tar.xz |
Merge tag 'net-next-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from Jakub Kicinski:
"Core:
- support "prefer busy polling" NAPI operation mode, where we defer
softirq for some time expecting applications to periodically busy
poll
- AF_XDP: improve efficiency by more batching and hindering the
adjacency cache prefetcher
- af_packet: make packet_fanout.arr size configurable up to 64K
- tcp: optimize TCP zero copy receive in presence of partial or
unaligned reads making zero copy a performance win for much smaller
messages
- XDP: add bulk APIs for returning / freeing frames
- sched: support fragmenting IP packets as they come out of conntrack
- net: allow virtual netdevs to forward UDP L4 and fraglist GSO skbs
BPF:
- BPF switch from crude rlimit-based to memcg-based memory accounting
- BPF type format information for kernel modules and related tracing
enhancements
- BPF implement task local storage for BPF LSM
- allow the FENTRY/FEXIT/RAW_TP tracing programs to use
bpf_sk_storage
Protocols:
- mptcp: improve multiple xmit streams support, memory accounting and
many smaller improvements
- TLS: support CHACHA20-POLY1305 cipher
- seg6: add support for SRv6 End.DT4/DT6 behavior
- sctp: Implement RFC 6951: UDP Encapsulation of SCTP
- ppp_generic: add ability to bridge channels directly
- bridge: Connectivity Fault Management (CFM) support as is defined
in IEEE 802.1Q section 12.14.
Drivers:
- mlx5: make use of the new auxiliary bus to organize the driver
internals
- mlx5: more accurate port TX timestamping support
- mlxsw:
- improve the efficiency of offloaded next hop updates by using
the new nexthop object API
- support blackhole nexthops
- support IEEE 802.1ad (Q-in-Q) bridging
- rtw88: major bluetooth co-existance improvements
- iwlwifi: support new 6 GHz frequency band
- ath11k: Fast Initial Link Setup (FILS)
- mt7915: dual band concurrent (DBDC) support
- net: ipa: add basic support for IPA v4.5
Refactor:
- a few pieces of in_interrupt() cleanup work from Sebastian Andrzej
Siewior
- phy: add support for shared interrupts; get rid of multiple driver
APIs and have the drivers write a full IRQ handler, slight growth
of driver code should be compensated by the simpler API which also
allows shared IRQs
- add common code for handling netdev per-cpu counters
- move TX packet re-allocation from Ethernet switch tag drivers to a
central place
- improve efficiency and rename nla_strlcpy
- number of W=1 warning cleanups as we now catch those in a patchwork
build bot
Old code removal:
- wan: delete the DLCI / SDLA drivers
- wimax: move to staging
- wifi: remove old WDS wifi bridging support"
* tag 'net-next-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1922 commits)
net: hns3: fix expression that is currently always true
net: fix proc_fs init handling in af_packet and tls
nfc: pn533: convert comma to semicolon
af_vsock: Assign the vsock transport considering the vsock address flags
af_vsock: Set VMADDR_FLAG_TO_HOST flag on the receive path
vsock_addr: Check for supported flag values
vm_sockets: Add VMADDR_FLAG_TO_HOST vsock flag
vm_sockets: Add flags field in the vsock address data structure
net: Disable NETIF_F_HW_TLS_TX when HW_CSUM is disabled
tcp: Add logic to check for SYN w/ data in tcp_simple_retransmit
net: mscc: ocelot: install MAC addresses in .ndo_set_rx_mode from process context
nfc: s3fwrn5: Release the nfc firmware
net: vxget: clean up sparse warnings
mlxsw: spectrum_router: Use eXtended mezzanine to offload IPv4 router
mlxsw: spectrum: Set KVH XLT cache mode for Spectrum2/3
mlxsw: spectrum_router_xm: Introduce basic XM cache flushing
mlxsw: reg: Add Router LPM Cache Enable Register
mlxsw: reg: Add Router LPM Cache ML Delete Register
mlxsw: spectrum_router_xm: Implement L-value tracking for M-index
mlxsw: reg: Add XM Router M Table Register
...
Diffstat (limited to 'drivers/net/wireless/intersil/orinoco/orinoco_usb.c')
-rw-r--r-- | drivers/net/wireless/intersil/orinoco/orinoco_usb.c | 168 |
1 files changed, 106 insertions, 62 deletions
diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c index b849d27bd741..dd31929261ab 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c @@ -665,26 +665,43 @@ static void ezusb_request_in_callback(struct ezusb_priv *upriv, } /* switch */ } +typedef void (*ezusb_ctx_wait)(struct ezusb_priv *, struct request_context *); -static void ezusb_req_ctx_wait(struct ezusb_priv *upriv, - struct request_context *ctx) +static void ezusb_req_ctx_wait_compl(struct ezusb_priv *upriv, + struct request_context *ctx) { switch (ctx->state) { case EZUSB_CTX_QUEUED: case EZUSB_CTX_REQ_SUBMITTED: case EZUSB_CTX_REQ_COMPLETE: case EZUSB_CTX_RESP_RECEIVED: - if (in_softirq()) { - /* If we get called from a timer, timeout timers don't - * get the chance to run themselves. So we make sure - * that we don't sleep for ever */ - int msecs = DEF_TIMEOUT * (1000 / HZ); - - while (!try_wait_for_completion(&ctx->done) && msecs--) - udelay(1000); - } else { - wait_for_completion(&ctx->done); - } + wait_for_completion(&ctx->done); + break; + default: + /* Done or failed - nothing to wait for */ + break; + } +} + +static void ezusb_req_ctx_wait_poll(struct ezusb_priv *upriv, + struct request_context *ctx) +{ + int msecs; + + switch (ctx->state) { + case EZUSB_CTX_QUEUED: + case EZUSB_CTX_REQ_SUBMITTED: + case EZUSB_CTX_REQ_COMPLETE: + case EZUSB_CTX_RESP_RECEIVED: + /* If we get called from a timer or with our lock acquired, then + * we can't wait for the completion and have to poll. This won't + * happen if the USB controller completes the URB requests in + * BH. + */ + msecs = DEF_TIMEOUT * (1000 / HZ); + + while (!try_wait_for_completion(&ctx->done) && msecs--) + udelay(1000); break; default: /* Done or failed - nothing to wait for */ @@ -692,6 +709,12 @@ static void ezusb_req_ctx_wait(struct ezusb_priv *upriv, } } +static void ezusb_req_ctx_wait_skip(struct ezusb_priv *upriv, + struct request_context *ctx) +{ + WARN(1, "Shouldn't be invoked for in_rid\n"); +} + static inline u16 build_crc(struct ezusb_packet *data) { u16 crc = 0; @@ -853,14 +876,13 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv, static int ezusb_access_ltv(struct ezusb_priv *upriv, struct request_context *ctx, u16 length, const void *data, u16 frame_type, - void *ans_buff, unsigned ans_size, u16 *ans_length) + void *ans_buff, unsigned ans_size, u16 *ans_length, + ezusb_ctx_wait ezusb_ctx_wait_func) { int req_size; int retval = 0; enum ezusb_state state; - BUG_ON(in_irq()); - if (!upriv->udev) { retval = -ENODEV; goto exit; @@ -885,7 +907,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv, spin_unlock_bh(&upriv->reply_count_lock); if (ctx->in_rid) - ezusb_req_ctx_wait(upriv, ctx); + ezusb_ctx_wait_func(upriv, ctx); state = ctx->state; switch (state) { @@ -946,8 +968,9 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv, return retval; } -static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid, - u16 length, const void *data) +static int __ezusb_write_ltv(struct hermes *hw, int bap, u16 rid, + u16 length, const void *data, + ezusb_ctx_wait ezusb_ctx_wait_func) { struct ezusb_priv *upriv = hw->priv; u16 frame_type; @@ -973,11 +996,20 @@ static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid, frame_type = EZUSB_FRAME_CONTROL; return ezusb_access_ltv(upriv, ctx, length, data, frame_type, - NULL, 0, NULL); + NULL, 0, NULL, ezusb_ctx_wait_func); } -static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid, - unsigned bufsize, u16 *length, void *buf) +static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid, + u16 length, const void *data) +{ + return __ezusb_write_ltv(hw, bap, rid, length, data, + ezusb_req_ctx_wait_poll); +} + +static int __ezusb_read_ltv(struct hermes *hw, int bap, u16 rid, + unsigned bufsize, u16 *length, void *buf, + ezusb_ctx_wait ezusb_ctx_wait_func) + { struct ezusb_priv *upriv = hw->priv; struct request_context *ctx; @@ -990,34 +1022,33 @@ static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid, return -ENOMEM; return ezusb_access_ltv(upriv, ctx, 0, NULL, EZUSB_FRAME_CONTROL, - buf, bufsize, length); + buf, bufsize, length, ezusb_req_ctx_wait_poll); } -static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1, - u16 parm2, struct hermes_response *resp) +static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid, + unsigned bufsize, u16 *length, void *buf) { - struct ezusb_priv *upriv = hw->priv; - struct request_context *ctx; + return __ezusb_read_ltv(hw, bap, rid, bufsize, length, buf, + ezusb_req_ctx_wait_poll); +} - __le16 data[4] = { - cpu_to_le16(cmd), - cpu_to_le16(parm0), - cpu_to_le16(parm1), - cpu_to_le16(parm2), - }; - netdev_dbg(upriv->dev, - "0x%04X, parm0 0x%04X, parm1 0x%04X, parm2 0x%04X\n", cmd, - parm0, parm1, parm2); - ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK); - if (!ctx) - return -ENOMEM; +static int ezusb_read_ltv_preempt(struct hermes *hw, int bap, u16 rid, + unsigned bufsize, u16 *length, void *buf) +{ + return __ezusb_read_ltv(hw, bap, rid, bufsize, length, buf, + ezusb_req_ctx_wait_compl); +} - return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, - EZUSB_FRAME_CONTROL, NULL, 0, NULL); +static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1, + u16 parm2, struct hermes_response *resp) +{ + WARN_ON_ONCE(1); + return -EINVAL; } -static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0, - struct hermes_response *resp) +static int __ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0, + struct hermes_response *resp, + ezusb_ctx_wait ezusb_ctx_wait_func) { struct ezusb_priv *upriv = hw->priv; struct request_context *ctx; @@ -1034,7 +1065,14 @@ static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0, return -ENOMEM; return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, - EZUSB_FRAME_CONTROL, NULL, 0, NULL); + EZUSB_FRAME_CONTROL, NULL, 0, NULL, + ezusb_ctx_wait_func); +} + +static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0, + struct hermes_response *resp) +{ + return __ezusb_docmd_wait(hw, cmd, parm0, resp, ezusb_req_ctx_wait_poll); } static int ezusb_bap_pread(struct hermes *hw, int bap, @@ -1092,7 +1130,7 @@ static int ezusb_read_pda(struct hermes *hw, __le16 *pda, return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, EZUSB_FRAME_CONTROL, &pda[2], pda_len - 4, - NULL); + NULL, ezusb_req_ctx_wait_compl); } static int ezusb_program_init(struct hermes *hw, u32 entry_point) @@ -1106,7 +1144,8 @@ static int ezusb_program_init(struct hermes *hw, u32 entry_point) return -ENOMEM; return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, - EZUSB_FRAME_CONTROL, NULL, 0, NULL); + EZUSB_FRAME_CONTROL, NULL, 0, NULL, + ezusb_req_ctx_wait_compl); } static int ezusb_program_end(struct hermes *hw) @@ -1119,7 +1158,8 @@ static int ezusb_program_end(struct hermes *hw) return -ENOMEM; return ezusb_access_ltv(upriv, ctx, 0, NULL, - EZUSB_FRAME_CONTROL, NULL, 0, NULL); + EZUSB_FRAME_CONTROL, NULL, 0, NULL, + ezusb_req_ctx_wait_compl); } static int ezusb_program_bytes(struct hermes *hw, const char *buf, @@ -1135,7 +1175,8 @@ static int ezusb_program_bytes(struct hermes *hw, const char *buf, return -ENOMEM; err = ezusb_access_ltv(upriv, ctx, sizeof(data), &data, - EZUSB_FRAME_CONTROL, NULL, 0, NULL); + EZUSB_FRAME_CONTROL, NULL, 0, NULL, + ezusb_req_ctx_wait_compl); if (err) return err; @@ -1144,7 +1185,8 @@ static int ezusb_program_bytes(struct hermes *hw, const char *buf, return -ENOMEM; return ezusb_access_ltv(upriv, ctx, len, buf, - EZUSB_FRAME_CONTROL, NULL, 0, NULL); + EZUSB_FRAME_CONTROL, NULL, 0, NULL, + ezusb_req_ctx_wait_compl); } static int ezusb_program(struct hermes *hw, const char *buf, @@ -1223,13 +1265,6 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) if (skb->len < ETH_HLEN) goto drop; - ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0); - if (!ctx) - goto busy; - - memset(ctx->buf, 0, BULK_BUF_SIZE); - buf = ctx->buf->data; - tx_control = 0; err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control, @@ -1237,6 +1272,13 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) if (err) goto drop; + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0); + if (!ctx) + goto drop; + + memset(ctx->buf, 0, BULK_BUF_SIZE); + buf = ctx->buf->data; + { __le16 *tx_cntl = (__le16 *)buf; *tx_cntl = cpu_to_le16(tx_control); @@ -1264,7 +1306,8 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) tx_size = ALIGN(buf - ctx->buf->data, 2); err = ezusb_access_ltv(upriv, ctx, tx_size, NULL, - EZUSB_FRAME_DATA, NULL, 0, NULL); + EZUSB_FRAME_DATA, NULL, 0, NULL, + ezusb_req_ctx_wait_skip); if (err) { netif_start_queue(dev); @@ -1349,7 +1392,6 @@ static int ezusb_init(struct hermes *hw) struct ezusb_priv *upriv = hw->priv; int retval; - BUG_ON(in_interrupt()); if (!upriv) return -EINVAL; @@ -1362,14 +1404,16 @@ static int ezusb_init(struct hermes *hw) usb_kill_urb(upriv->read_urb); ezusb_submit_in_urb(upriv); - retval = ezusb_write_ltv(hw, 0, EZUSB_RID_INIT1, - HERMES_BYTES_TO_RECLEN(2), "\x10\x00"); + retval = __ezusb_write_ltv(hw, 0, EZUSB_RID_INIT1, + HERMES_BYTES_TO_RECLEN(2), "\x10\x00", + ezusb_req_ctx_wait_compl); if (retval < 0) { printk(KERN_ERR PFX "EZUSB_RID_INIT1 error %d\n", retval); return retval; } - retval = ezusb_docmd_wait(hw, HERMES_CMD_INIT, 0, NULL); + retval = __ezusb_docmd_wait(hw, HERMES_CMD_INIT, 0, NULL, + ezusb_req_ctx_wait_compl); if (retval < 0) { printk(KERN_ERR PFX "HERMES_CMD_INIT error %d\n", retval); return retval; @@ -1448,7 +1492,6 @@ static inline void ezusb_delete(struct ezusb_priv *upriv) struct list_head *tmp_item; unsigned long flags; - BUG_ON(in_interrupt()); BUG_ON(!upriv); mutex_lock(&upriv->mtx); @@ -1533,6 +1576,7 @@ static const struct hermes_ops ezusb_ops = { .init_cmd_wait = ezusb_doicmd_wait, .allocate = ezusb_allocate, .read_ltv = ezusb_read_ltv, + .read_ltv_pr = ezusb_read_ltv_preempt, .write_ltv = ezusb_write_ltv, .bap_pread = ezusb_bap_pread, .read_pda = ezusb_read_pda, |