diff options
author | Linus Torvalds | 2023-02-21 18:24:12 -0800 |
---|---|---|
committer | Linus Torvalds | 2023-02-21 18:24:12 -0800 |
commit | 5b7c4cabbb65f5c469464da6c5f614cbd7f730f2 (patch) | |
tree | cc5c2d0a898769fd59549594fedb3ee6f84e59a0 /drivers/s390 | |
parent | 36289a03bcd3aabdf66de75cb6d1b4ee15726438 (diff) | |
parent | d1fabc68f8e0541d41657096dc713cb01775652d (diff) |
Merge tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from Jakub Kicinski:
"Core:
- Add dedicated kmem_cache for typical/small skb->head, avoid having
to access struct page at kfree time, and improve memory use.
- Introduce sysctl to set default RPS configuration for new netdevs.
- Define Netlink protocol specification format which can be used to
describe messages used by each family and auto-generate parsers.
Add tools for generating kernel data structures and uAPI headers.
- Expose all net/core sysctls inside netns.
- Remove 4s sleep in netpoll if carrier is instantly detected on
boot.
- Add configurable limit of MDB entries per port, and port-vlan.
- Continue populating drop reasons throughout the stack.
- Retire a handful of legacy Qdiscs and classifiers.
Protocols:
- Support IPv4 big TCP (TSO frames larger than 64kB).
- Add IP_LOCAL_PORT_RANGE socket option, to control local port range
on socket by socket basis.
- Track and report in procfs number of MPTCP sockets used.
- Support mixing IPv4 and IPv6 flows in the in-kernel MPTCP path
manager.
- IPv6: don't check net.ipv6.route.max_size and rely on garbage
collection to free memory (similarly to IPv4).
- Support Penultimate Segment Pop (PSP) flavor in SRv6 (RFC8986).
- ICMP: add per-rate limit counters.
- Add support for user scanning requests in ieee802154.
- Remove static WEP support.
- Support minimal Wi-Fi 7 Extremely High Throughput (EHT) rate
reporting.
- WiFi 7 EHT channel puncturing support (client & AP).
BPF:
- Add a rbtree data structure following the "next-gen data structure"
precedent set by recently added linked list, that is, by using
kfunc + kptr instead of adding a new BPF map type.
- Expose XDP hints via kfuncs with initial support for RX hash and
timestamp metadata.
- Add BPF_F_NO_TUNNEL_KEY extension to bpf_skb_set_tunnel_key to
better support decap on GRE tunnel devices not operating in collect
metadata.
- Improve x86 JIT's codegen for PROBE_MEM runtime error checks.
- Remove the need for trace_printk_lock for bpf_trace_printk and
bpf_trace_vprintk helpers.
- Extend libbpf's bpf_tracing.h support for tracing arguments of
kprobes/uprobes and syscall as a special case.
- Significantly reduce the search time for module symbols by
livepatch and BPF.
- Enable cpumasks to be used as kptrs, which is useful for tracing
programs tracking which tasks end up running on which CPUs in
different time intervals.
- Add support for BPF trampoline on s390x and riscv64.
- Add capability to export the XDP features supported by the NIC.
- Add __bpf_kfunc tag for marking kernel functions as kfuncs.
- Add cgroup.memory=nobpf kernel parameter option to disable BPF
memory accounting for container environments.
Netfilter:
- Remove the CLUSTERIP target. It has been marked as obsolete for
years, and we still have WARN splats wrt races of the out-of-band
/proc interface installed by this target.
- Add 'destroy' commands to nf_tables. They are identical to the
existing 'delete' commands, but do not return an error if the
referenced object (set, chain, rule...) did not exist.
Driver API:
- Improve cpumask_local_spread() locality to help NICs set the right
IRQ affinity on AMD platforms.
- Separate C22 and C45 MDIO bus transactions more clearly.
- Introduce new DCB table to control DSCP rewrite on egress.
- Support configuration of Physical Layer Collision Avoidance (PLCA)
Reconciliation Sublayer (RS) (802.3cg-2019). Modern version of
shared medium Ethernet.
- Support for MAC Merge layer (IEEE 802.3-2018 clause 99). Allowing
preemption of low priority frames by high priority frames.
- Add support for controlling MACSec offload using netlink SET.
- Rework devlink instance refcounts to allow registration and
de-registration under the instance lock. Split the code into
multiple files, drop some of the unnecessarily granular locks and
factor out common parts of netlink operation handling.
- Add TX frame aggregation parameters (for USB drivers).
- Add a new attr TCA_EXT_WARN_MSG to report TC (offload) warning
messages with notifications for debug.
- Allow offloading of UDP NEW connections via act_ct.
- Add support for per action HW stats in TC.
- Support hardware miss to TC action (continue processing in SW from
a specific point in the action chain).
- Warn if old Wireless Extension user space interface is used with
modern cfg80211/mac80211 drivers. Do not support Wireless
Extensions for Wi-Fi 7 devices at all. Everyone should switch to
using nl80211 interface instead.
- Improve the CAN bit timing configuration. Use extack to return
error messages directly to user space, update the SJW handling,
including the definition of a new default value that will benefit
CAN-FD controllers, by increasing their oscillator tolerance.
New hardware / drivers:
- Ethernet:
- nVidia BlueField-3 support (control traffic driver)
- Ethernet support for imx93 SoCs
- Motorcomm yt8531 gigabit Ethernet PHY
- onsemi NCN26000 10BASE-T1S PHY (with support for PLCA)
- Microchip LAN8841 PHY (incl. cable diagnostics and PTP)
- Amlogic gxl MDIO mux
- WiFi:
- RealTek RTL8188EU (rtl8xxxu)
- Qualcomm Wi-Fi 7 devices (ath12k)
- CAN:
- Renesas R-Car V4H
Drivers:
- Bluetooth:
- Set Per Platform Antenna Gain (PPAG) for Intel controllers.
- Ethernet NICs:
- Intel (1G, igc):
- support TSN / Qbv / packet scheduling features of i226 model
- Intel (100G, ice):
- use GNSS subsystem instead of TTY
- multi-buffer XDP support
- extend support for GPIO pins to E823 devices
- nVidia/Mellanox:
- update the shared buffer configuration on PFC commands
- implement PTP adjphase function for HW offset control
- TC support for Geneve and GRE with VF tunnel offload
- more efficient crypto key management method
- multi-port eswitch support
- Netronome/Corigine:
- add DCB IEEE support
- support IPsec offloading for NFP3800
- Freescale/NXP (enetc):
- support XDP_REDIRECT for XDP non-linear buffers
- improve reconfig, avoid link flap and waiting for idle
- support MAC Merge layer
- Other NICs:
- sfc/ef100: add basic devlink support for ef100
- ionic: rx_push mode operation (writing descriptors via MMIO)
- bnxt: use the auxiliary bus abstraction for RDMA
- r8169: disable ASPM and reset bus in case of tx timeout
- cpsw: support QSGMII mode for J721e CPSW9G
- cpts: support pulse-per-second output
- ngbe: add an mdio bus driver
- usbnet: optimize usbnet_bh() by avoiding unnecessary queuing
- r8152: handle devices with FW with NCM support
- amd-xgbe: support 10Mbps, 2.5GbE speeds and rx-adaptation
- virtio-net: support multi buffer XDP
- virtio/vsock: replace virtio_vsock_pkt with sk_buff
- tsnep: XDP support
- Ethernet high-speed switches:
- nVidia/Mellanox (mlxsw):
- add support for latency TLV (in FW control messages)
- Microchip (sparx5):
- separate explicit and implicit traffic forwarding rules, make
the implicit rules always active
- add support for egress DSCP rewrite
- IS0 VCAP support (Ingress Classification)
- IS2 VCAP filters (protos, L3 addrs, L4 ports, flags, ToS
etc.)
- ES2 VCAP support (Egress Access Control)
- support for Per-Stream Filtering and Policing (802.1Q,
8.6.5.1)
- Ethernet embedded switches:
- Marvell (mv88e6xxx):
- add MAB (port auth) offload support
- enable PTP receive for mv88e6390
- NXP (ocelot):
- support MAC Merge layer
- support for the the vsc7512 internal copper phys
- Microchip:
- lan9303: convert to PHYLINK
- lan966x: support TC flower filter statistics
- lan937x: PTP support for KSZ9563/KSZ8563 and LAN937x
- lan937x: support Credit Based Shaper configuration
- ksz9477: support Energy Efficient Ethernet
- other:
- qca8k: convert to regmap read/write API, use bulk operations
- rswitch: Improve TX timestamp accuracy
- Intel WiFi (iwlwifi):
- EHT (Wi-Fi 7) rate reporting
- STEP equalizer support: transfer some STEP (connection to radio
on platforms with integrated wifi) related parameters from the
BIOS to the firmware.
- Qualcomm 802.11ax WiFi (ath11k):
- IPQ5018 support
- Fine Timing Measurement (FTM) responder role support
- channel 177 support
- MediaTek WiFi (mt76):
- per-PHY LED support
- mt7996: EHT (Wi-Fi 7) support
- Wireless Ethernet Dispatch (WED) reset support
- switch to using page pool allocator
- RealTek WiFi (rtw89):
- support new version of Bluetooth co-existance
- Mobile:
- rmnet: support TX aggregation"
* tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1872 commits)
page_pool: add a comment explaining the fragment counter usage
net: ethtool: fix __ethtool_dev_mm_supported() implementation
ethtool: pse-pd: Fix double word in comments
xsk: add linux/vmalloc.h to xsk.c
sefltests: netdevsim: wait for devlink instance after netns removal
selftest: fib_tests: Always cleanup before exit
net/mlx5e: Align IPsec ASO result memory to be as required by hardware
net/mlx5e: TC, Set CT miss to the specific ct action instance
net/mlx5e: Rename CHAIN_TO_REG to MAPPED_OBJ_TO_REG
net/mlx5: Refactor tc miss handling to a single function
net/mlx5: Kconfig: Make tc offload depend on tc skb extension
net/sched: flower: Support hardware miss to tc action
net/sched: flower: Move filter handle initialization earlier
net/sched: cls_api: Support hardware miss to tc action
net/sched: Rename user cookie and act cookie
sfc: fix builds without CONFIG_RTC_LIB
sfc: clean up some inconsistent indentings
net/mlx4_en: Introduce flexible array to silence overflow warning
net: lan966x: Fix possible deadlock inside PTP
net/ulp: Remove redundant ->clone() test in inet_clone_ulp().
...
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/net/ctcm_fsms.c | 32 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_main.c | 16 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_mpc.c | 15 | ||||
-rw-r--r-- | drivers/s390/net/ism.h | 19 | ||||
-rw-r--r-- | drivers/s390/net/ism_drv.c | 376 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 14 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_sys.c | 66 | ||||
-rw-r--r-- | drivers/s390/net/qeth_ethtool.c | 6 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 53 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_sys.c | 28 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 7 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_sys.c | 83 |
12 files changed, 456 insertions, 259 deletions
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c index dfb84bb03d32..90ec477386a8 100644 --- a/drivers/s390/net/ctcm_fsms.c +++ b/drivers/s390/net/ctcm_fsms.c @@ -370,7 +370,7 @@ static void chx_rx(fsm_instance *fi, int event, void *arg) CTCM_FUNTAIL, dev->name, len); priv->stats.rx_dropped++; priv->stats.rx_length_errors++; - goto again; + goto again; } if (len > ch->max_bufsize) { CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE, @@ -378,7 +378,7 @@ static void chx_rx(fsm_instance *fi, int event, void *arg) CTCM_FUNTAIL, dev->name, len, ch->max_bufsize); priv->stats.rx_dropped++; priv->stats.rx_length_errors++; - goto again; + goto again; } /* @@ -403,7 +403,7 @@ static void chx_rx(fsm_instance *fi, int event, void *arg) *((__u16 *)skb->data) = len; priv->stats.rx_dropped++; priv->stats.rx_length_errors++; - goto again; + goto again; } if (block_len > 2) { *((__u16 *)skb->data) = block_len - 2; @@ -1006,7 +1006,7 @@ static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg) use gptr as mpc indicator */ if (!(gptr && (fsm_getstate(gptr->fsm) != MPCG_STATE_READY))) ctcm_chx_restart(fi, event, arg); - goto done; + goto done; } CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, @@ -1024,7 +1024,7 @@ static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg) CTCM_FUNTAIL, ch->id); fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev); ctcm_chx_restart(fi, event, arg); - goto done; + goto done; } fsm_addtimer(&ch->timer, 1000, CTC_EVENT_TIMER, ch); if (event == CTC_EVENT_TIMER) /* for TIMER not yet locked */ @@ -1251,12 +1251,12 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg) if ((ch->collect_len <= 0) || (grp->in_sweep != 0)) { spin_unlock(&ch->collect_lock); fsm_newstate(fi, CTC_STATE_TXIDLE); - goto done; + goto done; } if (ctcm_checkalloc_buffer(ch)) { spin_unlock(&ch->collect_lock); - goto done; + goto done; } ch->trans_skb->data = ch->trans_skb_data; skb_reset_tail_pointer(ch->trans_skb); @@ -1389,7 +1389,7 @@ static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg) CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, "%s(%s): TRANS_SKB = NULL", CTCM_FUNTAIL, dev->name); - goto again; + goto again; } if (len < TH_HEADER_LENGTH) { @@ -1409,7 +1409,7 @@ static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg) "%s(%s): skb allocation failed", CTCM_FUNTAIL, dev->name); fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev); - goto again; + goto again; } switch (fsm_getstate(grp->fsm)) { case MPCG_STATE_RESET: @@ -1441,9 +1441,9 @@ again: skb_reset_tail_pointer(ch->trans_skb); ch->trans_skb->len = 0; ch->ccw[1].count = ch->max_bufsize; - if (do_debug_ccw) + if (do_debug_ccw) ctcmpc_dumpit((char *)&ch->ccw[0], - sizeof(struct ccw1) * 3); + sizeof(struct ccw1) * 3); dolock = !in_hardirq(); if (dolock) spin_lock_irqsave( @@ -1562,7 +1562,7 @@ void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg) if (rc != 0) { fsm_newstate(fi, CTC_STATE_RXINIT); ctcm_ccw_check_rc(ch, rc, "initial RX"); - goto done; + goto done; } break; default: @@ -1677,10 +1677,10 @@ static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg) if (fsm_getstate(ch->fsm) == CH_XID0_INPROGRESS) { fsm_newstate(ch->fsm, CH_XID0_PENDING) ; fsm_deltimer(&grp->timer); - goto done; + goto done; } fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); - goto done; + goto done; case MPCG_STATE_XID2INITX: /* XID2 was received before ATTN Busy for second channel.Send yside xid for second channel. @@ -1768,7 +1768,7 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg) /* give the previous IO time to complete */ fsm_addtimer(&wch->sweep_timer, 200, CTC_EVENT_RSWEEP_TIMER, wch); - goto done; + goto done; } skb = skb_dequeue(&wch->sweep_queue); @@ -1780,7 +1780,7 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg) ctcm_clear_busy_do(dev); dev_kfree_skb_any(skb); fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); - goto done; + goto done; } else { refcount_inc(&skb->users); skb_queue_tail(&wch->io_queue, skb); diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index bdfab9ea0046..28db69d91f17 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -494,7 +494,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb) ch->collect_len += l; } spin_unlock_irqrestore(&ch->collect_lock, saveflags); - goto done; + goto done; } spin_unlock_irqrestore(&ch->collect_lock, saveflags); /* @@ -685,7 +685,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) ch->collect_len += skb->len; spin_unlock_irqrestore(&ch->collect_lock, saveflags); - goto done; + goto done; } /* @@ -885,7 +885,7 @@ static netdev_tx_t ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) "%s(%s): NULL sk_buff passed", CTCM_FUNTAIL, dev->name); priv->stats.tx_dropped++; - goto done; + goto done; } if (skb_headroom(skb) < (TH_HEADER_LENGTH + PDU_HEADER_LENGTH)) { CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR, @@ -908,7 +908,7 @@ static netdev_tx_t ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) priv->stats.tx_errors++; priv->stats.tx_carrier_errors++; fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); - goto done; + goto done; } newskb->protocol = skb->protocol; skb_reserve(newskb, TH_HEADER_LENGTH + PDU_HEADER_LENGTH); @@ -931,7 +931,7 @@ static netdev_tx_t ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) priv->stats.tx_dropped++; priv->stats.tx_errors++; priv->stats.tx_carrier_errors++; - goto done; + goto done; } if (ctcm_test_and_set_busy(dev)) { @@ -943,7 +943,7 @@ static netdev_tx_t ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) priv->stats.tx_errors++; priv->stats.tx_carrier_errors++; fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); - goto done; + goto done; } netif_trans_update(dev); @@ -957,7 +957,7 @@ static netdev_tx_t ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) priv->stats.tx_carrier_errors++; ctcm_clear_busy(dev); fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); - goto done; + goto done; } ctcm_clear_busy(dev); done: @@ -1421,7 +1421,7 @@ static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type, "%s (%s) already in list, using old entry", __func__, (*c)->id); - goto free_return; + goto free_return; } spin_lock_init(&ch->collect_lock); diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index 8ac213a55141..b8a226c6e1a9 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c @@ -481,7 +481,7 @@ void ctc_mpc_establish_connectivity(int port_num, grp->estconnfunc = NULL; } fsm_deltimer(&grp->timer); - goto done; + goto done; } if ((wch->in_mpcgroup) && (fsm_getstate(wch->fsm) == CH_XID0_PENDING)) @@ -495,7 +495,7 @@ void ctc_mpc_establish_connectivity(int port_num, grp->estconnfunc = NULL; } fsm_deltimer(&grp->timer); - goto done; + goto done; } break; case MPCG_STATE_XID0IOWAIT: @@ -896,8 +896,9 @@ void mpc_group_ready(unsigned long adev) grp->estconnfunc(grp->port_num, 0, grp->group_max_buflen); grp->estconnfunc = NULL; - } else if (grp->allochanfunc) + } else if (grp->allochanfunc) { grp->allochanfunc(grp->port_num, grp->group_max_buflen); + } grp->send_qllc_disc = 1; grp->changed_side = 0; @@ -1109,7 +1110,7 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb) priv->stats.rx_dropped++; priv->stats.rx_length_errors++; - goto done; + goto done; } skb_reset_mac_header(pskb); new_len = curr_pdu->pdu_offset; @@ -1132,7 +1133,7 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb) CTCM_FUNTAIL, dev->name); priv->stats.rx_dropped++; fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); - goto done; + goto done; } skb_put_data(skb, pskb->data, new_len); @@ -1543,7 +1544,7 @@ static int mpc_validate_xid(struct mpcg_info *mpcginfo) CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, "%s(%s): xid = NULL", CTCM_FUNTAIL, ch->id); - goto done; + goto done; } CTCM_D3_DUMP((char *)xid, XID2_LENGTH); @@ -1556,7 +1557,7 @@ static int mpc_validate_xid(struct mpcg_info *mpcginfo) CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, "%s(%s): r/w channel pairing mismatch", CTCM_FUNTAIL, ch->id); - goto done; + goto done; } if (xid->xid2_dlc_type == XID2_READ_SIDE) { diff --git a/drivers/s390/net/ism.h b/drivers/s390/net/ism.h index 38fe90c2597d..70c5bbda0fea 100644 --- a/drivers/s390/net/ism.h +++ b/drivers/s390/net/ism.h @@ -5,6 +5,7 @@ #include <linux/spinlock.h> #include <linux/types.h> #include <linux/pci.h> +#include <linux/ism.h> #include <net/smc.h> #include <asm/pci_insn.h> @@ -15,7 +16,6 @@ */ #define ISM_DMB_WORD_OFFSET 1 #define ISM_DMB_BIT_OFFSET (ISM_DMB_WORD_OFFSET * 32) -#define ISM_NR_DMBS 1920 #define ISM_IDENT_MASK 0x00FFFF #define ISM_REG_SBA 0x1 @@ -177,7 +177,7 @@ struct ism_eq_header { struct ism_eq { struct ism_eq_header header; - struct smcd_event entry[15]; + struct ism_event entry[15]; }; struct ism_sba { @@ -189,21 +189,6 @@ struct ism_sba { u16 dmbe_mask[ISM_NR_DMBS]; }; -struct ism_dev { - spinlock_t lock; - struct pci_dev *pdev; - struct smcd_dev *smcd; - - struct ism_sba *sba; - dma_addr_t sba_dma_addr; - DECLARE_BITMAP(sba_bitmap, ISM_NR_DMBS); - - struct ism_eq *ieq; - dma_addr_t ieq_dma_addr; - - int ieq_idx; -}; - #define ISM_CREATE_REQ(dmb, idx, sf, offset) \ ((dmb) | (idx) << 24 | (sf) << 23 | (offset)) diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c index dfd401d9e362..eb7e13486087 100644 --- a/drivers/s390/net/ism_drv.c +++ b/drivers/s390/net/ism_drv.c @@ -15,9 +15,6 @@ #include <linux/err.h> #include <linux/ctype.h> #include <linux/processor.h> -#include <net/smc.h> - -#include <asm/debug.h> #include "ism.h" @@ -34,6 +31,84 @@ static const struct pci_device_id ism_device_table[] = { MODULE_DEVICE_TABLE(pci, ism_device_table); static debug_info_t *ism_debug_info; +static const struct smcd_ops ism_ops; + +#define NO_CLIENT 0xff /* must be >= MAX_CLIENTS */ +static struct ism_client *clients[MAX_CLIENTS]; /* use an array rather than */ + /* a list for fast mapping */ +static u8 max_client; +static DEFINE_SPINLOCK(clients_lock); +struct ism_dev_list { + struct list_head list; + struct mutex mutex; /* protects ism device list */ +}; + +static struct ism_dev_list ism_dev_list = { + .list = LIST_HEAD_INIT(ism_dev_list.list), + .mutex = __MUTEX_INITIALIZER(ism_dev_list.mutex), +}; + +int ism_register_client(struct ism_client *client) +{ + struct ism_dev *ism; + unsigned long flags; + int i, rc = -ENOSPC; + + mutex_lock(&ism_dev_list.mutex); + spin_lock_irqsave(&clients_lock, flags); + for (i = 0; i < MAX_CLIENTS; ++i) { + if (!clients[i]) { + clients[i] = client; + client->id = i; + if (i == max_client) + max_client++; + rc = 0; + break; + } + } + spin_unlock_irqrestore(&clients_lock, flags); + if (i < MAX_CLIENTS) { + /* initialize with all devices that we got so far */ + list_for_each_entry(ism, &ism_dev_list.list, list) { + ism->priv[i] = NULL; + client->add(ism); + } + } + mutex_unlock(&ism_dev_list.mutex); + + return rc; +} +EXPORT_SYMBOL_GPL(ism_register_client); + +int ism_unregister_client(struct ism_client *client) +{ + struct ism_dev *ism; + unsigned long flags; + int rc = 0; + + mutex_lock(&ism_dev_list.mutex); + spin_lock_irqsave(&clients_lock, flags); + clients[client->id] = NULL; + if (client->id + 1 == max_client) + max_client--; + spin_unlock_irqrestore(&clients_lock, flags); + list_for_each_entry(ism, &ism_dev_list.list, list) { + for (int i = 0; i < ISM_NR_DMBS; ++i) { + if (ism->sba_client_arr[i] == client->id) { + pr_err("%s: attempt to unregister client '%s'" + "with registered dmb(s)\n", __func__, + client->name); + rc = -EBUSY; + goto out; + } + } + } +out: + mutex_unlock(&ism_dev_list.mutex); + + return rc; +} +EXPORT_SYMBOL_GPL(ism_unregister_client); static int ism_cmd(struct ism_dev *ism, void *cmd) { @@ -193,15 +268,14 @@ static int ism_read_local_gid(struct ism_dev *ism) if (ret) goto out; - ism->smcd->local_gid = cmd.response.gid; + ism->local_gid = cmd.response.gid; out: return ret; } -static int ism_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid, +static int ism_query_rgid(struct ism_dev *ism, u64 rgid, u32 vid_valid, u32 vid) { - struct ism_dev *ism = smcd->priv; union ism_query_rgid cmd; memset(&cmd, 0, sizeof(cmd)); @@ -215,14 +289,14 @@ static int ism_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid, return ism_cmd(ism, &cmd); } -static void ism_free_dmb(struct ism_dev *ism, struct smcd_dmb *dmb) +static void ism_free_dmb(struct ism_dev *ism, struct ism_dmb *dmb) { clear_bit(dmb->sba_idx, ism->sba_bitmap); dma_free_coherent(&ism->pdev->dev, dmb->dmb_len, dmb->cpu_addr, dmb->dma_addr); } -static int ism_alloc_dmb(struct ism_dev *ism, struct smcd_dmb *dmb) +static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb) { unsigned long bit; @@ -251,9 +325,9 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct smcd_dmb *dmb) return dmb->cpu_addr ? 0 : -ENOMEM; } -static int ism_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb) +int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb, + struct ism_client *client) { - struct ism_dev *ism = smcd->priv; union ism_reg_dmb cmd; int ret; @@ -278,13 +352,14 @@ static int ism_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb) goto out; } dmb->dmb_tok = cmd.response.dmb_tok; + ism->sba_client_arr[dmb->sba_idx - ISM_DMB_BIT_OFFSET] = client->id; out: return ret; } +EXPORT_SYMBOL_GPL(ism_register_dmb); -static int ism_unregister_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb) +int ism_unregister_dmb(struct ism_dev *ism, struct ism_dmb *dmb) { - struct ism_dev *ism = smcd->priv; union ism_unreg_dmb cmd; int ret; @@ -294,6 +369,8 @@ static int ism_unregister_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb) cmd.request.dmb_tok = dmb->dmb_tok; + ism->sba_client_arr[dmb->sba_idx - ISM_DMB_BIT_OFFSET] = NO_CLIENT; + ret = ism_cmd(ism, &cmd); if (ret && ret != ISM_ERROR) goto out; @@ -302,10 +379,10 @@ static int ism_unregister_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb) out: return ret; } +EXPORT_SYMBOL_GPL(ism_unregister_dmb); -static int ism_add_vlan_id(struct smcd_dev *smcd, u64 vlan_id) +static int ism_add_vlan_id(struct ism_dev *ism, u64 vlan_id) { - struct ism_dev *ism = smcd->priv; union ism_set_vlan_id cmd; memset(&cmd, 0, sizeof(cmd)); @@ -317,9 +394,8 @@ static int ism_add_vlan_id(struct smcd_dev *smcd, u64 vlan_id) return ism_cmd(ism, &cmd); } -static int ism_del_vlan_id(struct smcd_dev *smcd, u64 vlan_id) +static int ism_del_vlan_id(struct ism_dev *ism, u64 vlan_id) { - struct ism_dev *ism = smcd->priv; union ism_set_vlan_id cmd; memset(&cmd, 0, sizeof(cmd)); @@ -331,20 +407,9 @@ static int ism_del_vlan_id(struct smcd_dev *smcd, u64 vlan_id) return ism_cmd(ism, &cmd); } -static int ism_set_vlan_required(struct smcd_dev *smcd) -{ - return ism_cmd_simple(smcd->priv, ISM_SET_VLAN); -} - -static int ism_reset_vlan_required(struct smcd_dev *smcd) -{ - return ism_cmd_simple(smcd->priv, ISM_RESET_VLAN); -} - -static int ism_signal_ieq(struct smcd_dev *smcd, u64 rgid, u32 trigger_irq, +static int ism_signal_ieq(struct ism_dev *ism, u64 rgid, u32 trigger_irq, u32 event_code, u64 info) { - struct ism_dev *ism = smcd->priv; union ism_sig_ieq cmd; memset(&cmd, 0, sizeof(cmd)); @@ -365,10 +430,9 @@ static unsigned int max_bytes(unsigned int start, unsigned int len, return min(boundary - (start & (boundary - 1)), len); } -static int ism_move(struct smcd_dev *smcd, u64 dmb_tok, unsigned int idx, - bool sf, unsigned int offset, void *data, unsigned int size) +int ism_move(struct ism_dev *ism, u64 dmb_tok, unsigned int idx, bool sf, + unsigned int offset, void *data, unsigned int size) { - struct ism_dev *ism = smcd->priv; unsigned int bytes; u64 dmb_req; int ret; @@ -389,6 +453,7 @@ static int ism_move(struct smcd_dev *smcd, u64 dmb_tok, unsigned int idx, return 0; } +EXPORT_SYMBOL_GPL(ism_move); static struct ism_systemeid SYSTEM_EID = { .seid_string = "IBM-SYSZ-ISMSEID00000000", @@ -410,15 +475,14 @@ static void ism_create_system_eid(void) memcpy(&SYSTEM_EID.type, tmp, 4); } -static u8 *ism_get_system_eid(void) +u8 *ism_get_seid(void) { return SYSTEM_EID.seid_string; } +EXPORT_SYMBOL_GPL(ism_get_seid); -static u16 ism_get_chid(struct smcd_dev *smcd) +static u16 ism_get_chid(struct ism_dev *ism) { - struct ism_dev *ism = (struct ism_dev *)smcd->priv; - if (!ism || !ism->pdev) return 0; @@ -427,7 +491,8 @@ static u16 ism_get_chid(struct smcd_dev *smcd) static void ism_handle_event(struct ism_dev *ism) { - struct smcd_event *entry; + struct ism_event *entry; + int i; while ((ism->ieq_idx + 1) != READ_ONCE(ism->ieq->header.idx)) { if (++(ism->ieq_idx) == ARRAY_SIZE(ism->ieq->entry)) @@ -435,13 +500,18 @@ static void ism_handle_event(struct ism_dev *ism) entry = &ism->ieq->entry[ism->ieq_idx]; debug_event(ism_debug_info, 2, entry, sizeof(*entry)); - smcd_handle_event(ism->smcd, entry); + spin_lock(&clients_lock); + for (i = 0; i < max_client; ++i) + if (clients[i]) + clients[i]->handle_event(ism, entry); + spin_unlock(&clients_lock); } } static irqreturn_t ism_handle_irq(int irq, void *data) { struct ism_dev *ism = data; + struct ism_client *clt; unsigned long bit, end; unsigned long *bv; u16 dmbemask; @@ -461,7 +531,8 @@ static irqreturn_t ism_handle_irq(int irq, void *data) dmbemask = ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET]; ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET] = 0; barrier(); - smcd_handle_irq(ism->smcd, bit + ISM_DMB_BIT_OFFSET, dmbemask); + clt = clients[ism->sba_client_arr[bit]]; + clt->handle_irq(ism, bit + ISM_DMB_BIT_OFFSET, dmbemask); } if (ism->sba->e) { @@ -473,33 +544,40 @@ static irqreturn_t ism_handle_irq(int irq, void *data) return IRQ_HANDLED; } -static const struct smcd_ops ism_ops = { - .query_remote_gid = ism_query_rgid, - .register_dmb = ism_register_dmb, - .unregister_dmb = ism_unregister_dmb, - .add_vlan_id = ism_add_vlan_id, - .del_vlan_id = ism_del_vlan_id, - .set_vlan_required = ism_set_vlan_required, - .reset_vlan_required = ism_reset_vlan_required, - .signal_event = ism_signal_ieq, - .move_data = ism_move, - .get_system_eid = ism_get_system_eid, - .get_chid = ism_get_chid, -}; +static u64 ism_get_local_gid(struct ism_dev *ism) +{ + return ism->local_gid; +} + +static void ism_dev_add_work_func(struct work_struct *work) +{ + struct ism_client *client = container_of(work, struct ism_client, + add_work); + + client->add(client->tgt_ism); + atomic_dec(&client->tgt_ism->add_dev_cnt); + wake_up(&client->tgt_ism->waitq); +} static int ism_dev_init(struct ism_dev *ism) { struct pci_dev *pdev = ism->pdev; - int ret; + unsigned long flags; + int i, ret; ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); if (ret <= 0) goto out; + ism->sba_client_arr = kzalloc(ISM_NR_DMBS, GFP_KERNEL); + if (!ism->sba_client_arr) + goto free_vectors; + memset(ism->sba_client_arr, NO_CLIENT, ISM_NR_DMBS); + ret = request_irq(pci_irq_vector(pdev, 0), ism_handle_irq, 0, pci_name(pdev), ism); if (ret) - goto free_vectors; + goto free_client_arr; ret = register_sba(ism); if (ret) @@ -513,13 +591,31 @@ static int ism_dev_init(struct ism_dev *ism) if (ret) goto unreg_ieq; - if (!ism_add_vlan_id(ism->smcd, ISM_RESERVED_VLANID)) + if (!ism_add_vlan_id(ism, ISM_RESERVED_VLANID)) /* hardware is V2 capable */ ism_create_system_eid(); - ret = smcd_register_dev(ism->smcd); - if (ret) - goto unreg_ieq; + init_waitqueue_head(&ism->waitq); + atomic_set(&ism->free_clients_cnt, 0); + atomic_set(&ism->add_dev_cnt, 0); + + wait_event(ism->waitq, !atomic_read(&ism->add_dev_cnt)); + spin_lock_irqsave(&clients_lock, flags); + for (i = 0; i < max_client; ++i) + if (clients[i]) { + INIT_WORK(&clients[i]->add_work, + ism_dev_add_work_func); + clients[i]->tgt_ism = ism; + atomic_inc(&ism->add_dev_cnt); + schedule_work(&clients[i]->add_work); + } + spin_unlock_irqrestore(&clients_lock, flags); + + wait_event(ism->waitq, !atomic_read(&ism->add_dev_cnt)); + + mutex_lock(&ism_dev_list.mutex); + list_add(&ism->list, &ism_dev_list.list); + mutex_unlock(&ism_dev_list.mutex); query_info(ism); return 0; @@ -530,6 +626,8 @@ unreg_sba: unregister_sba(ism); free_irq: free_irq(pci_irq_vector(pdev, 0), ism); +free_client_arr: + kfree(ism->sba_client_arr); free_vectors: pci_free_irq_vectors(pdev); out: @@ -548,6 +646,12 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&ism->lock); dev_set_drvdata(&pdev->dev, ism); ism->pdev = pdev; + ism->dev.parent = &pdev->dev; + device_initialize(&ism->dev); + dev_set_name(&ism->dev, dev_name(&pdev->dev)); + ret = device_add(&ism->dev); + if (ret) + goto err_dev; ret = pci_enable_device_mem(pdev); if (ret) @@ -565,55 +669,80 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) dma_set_max_seg_size(&pdev->dev, SZ_1M); pci_set_master(pdev); - ism->smcd = smcd_alloc_dev(&pdev->dev, dev_name(&pdev->dev), &ism_ops, - ISM_NR_DMBS); - if (!ism->smcd) { - ret = -ENOMEM; - goto err_resource; - } - - ism->smcd->priv = ism; ret = ism_dev_init(ism); if (ret) - goto err_free; + goto err_resource; return 0; -err_free: - smcd_free_dev(ism->smcd); err_resource: + pci_clear_master(pdev); pci_release_mem_regions(pdev); err_disable: pci_disable_device(pdev); err: - kfree(ism); + device_del(&ism->dev); +err_dev: dev_set_drvdata(&pdev->dev, NULL); + kfree(ism); + return ret; } +static void ism_dev_remove_work_func(struct work_struct *work) +{ + struct ism_client *client = container_of(work, struct ism_client, + remove_work); + + client->remove(client->tgt_ism); + atomic_dec(&client->tgt_ism->free_clients_cnt); + wake_up(&client->tgt_ism->waitq); +} + +/* Callers must hold ism_dev_list.mutex */ static void ism_dev_exit(struct ism_dev *ism) { struct pci_dev *pdev = ism->pdev; + unsigned long flags; + int i; + + wait_event(ism->waitq, !atomic_read(&ism->free_clients_cnt)); + spin_lock_irqsave(&clients_lock, flags); + for (i = 0; i < max_client; ++i) + if (clients[i]) { + INIT_WORK(&clients[i]->remove_work, + ism_dev_remove_work_func); + clients[i]->tgt_ism = ism; + atomic_inc(&ism->free_clients_cnt); + schedule_work(&clients[i]->remove_work); + } + spin_unlock_irqrestore(&clients_lock, flags); + + wait_event(ism->waitq, !atomic_read(&ism->free_clients_cnt)); - smcd_unregister_dev(ism->smcd); if (SYSTEM_EID.serial_number[0] != '0' || SYSTEM_EID.type[0] != '0') - ism_del_vlan_id(ism->smcd, ISM_RESERVED_VLANID); + ism_del_vlan_id(ism, ISM_RESERVED_VLANID); unregister_ieq(ism); unregister_sba(ism); free_irq(pci_irq_vector(pdev, 0), ism); + kfree(ism->sba_client_arr); pci_free_irq_vectors(pdev); + list_del_init(&ism->list); } static void ism_remove(struct pci_dev *pdev) { struct ism_dev *ism = dev_get_drvdata(&pdev->dev); + mutex_lock(&ism_dev_list.mutex); ism_dev_exit(ism); + mutex_unlock(&ism_dev_list.mutex); - smcd_free_dev(ism->smcd); + pci_clear_master(pdev); pci_release_mem_regions(pdev); pci_disable_device(pdev); + device_del(&ism->dev); dev_set_drvdata(&pdev->dev, NULL); kfree(ism); } @@ -633,6 +762,8 @@ static int __init ism_init(void) if (!ism_debug_info) return -ENODEV; + memset(clients, 0, sizeof(clients)); + max_client = 0; debug_register_view(ism_debug_info, &debug_hex_ascii_view); ret = pci_register_driver(&ism_driver); if (ret) @@ -643,9 +774,110 @@ static int __init ism_init(void) static void __exit ism_exit(void) { + struct ism_dev *ism; + + mutex_lock(&ism_dev_list.mutex); + list_for_each_entry(ism, &ism_dev_list.list, list) { + ism_dev_exit(ism); + } + mutex_unlock(&ism_dev_list.mutex); + pci_unregister_driver(&ism_driver); debug_unregister(ism_debug_info); } module_init(ism_init); module_exit(ism_exit); + +/*************************** SMC-D Implementation *****************************/ + +#if IS_ENABLED(CONFIG_SMC) +static int smcd_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid, + u32 vid) +{ + return ism_query_rgid(smcd->priv, rgid, vid_valid, vid); +} + +static int smcd_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb, + struct ism_client *client) +{ + return ism_register_dmb(smcd->priv, (struct ism_dmb *)dmb, client); +} + +static int smcd_unregister_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb) +{ + return ism_unregister_dmb(smcd->priv, (struct ism_dmb *)dmb); +} + +static int smcd_add_vlan_id(struct smcd_dev *smcd, u64 vlan_id) +{ + return ism_add_vlan_id(smcd->priv, vlan_id); +} + +static int smcd_del_vlan_id(struct smcd_dev *smcd, u64 vlan_id) +{ + return ism_del_vlan_id(smcd->priv, vlan_id); +} + +static int smcd_set_vlan_required(struct smcd_dev *smcd) +{ + return ism_cmd_simple(smcd->priv, ISM_SET_VLAN); +} + +static int smcd_reset_vlan_required(struct smcd_dev *smcd) +{ + return ism_cmd_simple(smcd->priv, ISM_RESET_VLAN); +} + +static int smcd_signal_ieq(struct smcd_dev *smcd, u64 rgid, u32 trigger_irq, + u32 event_code, u64 info) +{ + return ism_signal_ieq(smcd->priv, rgid, trigger_irq, event_code, info); +} + +static int smcd_move(struct smcd_dev *smcd, u64 dmb_tok, unsigned int idx, + bool sf, unsigned int offset, void *data, + unsigned int size) +{ + return ism_move(smcd->priv, dmb_tok, idx, sf, offset, data, size); +} + +static u64 smcd_get_local_gid(struct smcd_dev *smcd) +{ + return ism_get_local_gid(smcd->priv); +} + +static u16 smcd_get_chid(struct smcd_dev *smcd) +{ + return ism_get_chid(smcd->priv); +} + +static inline struct device *smcd_get_dev(struct smcd_dev *dev) +{ + struct ism_dev *ism = dev->priv; + + return &ism->dev; +} + +static const struct smcd_ops ism_ops = { + .query_remote_gid = smcd_query_rgid, + .register_dmb = smcd_register_dmb, + .unregister_dmb = smcd_unregister_dmb, + .add_vlan_id = smcd_add_vlan_id, + .del_vlan_id = smcd_del_vlan_id, + .set_vlan_required = smcd_set_vlan_required, + .reset_vlan_required = smcd_reset_vlan_required, + .signal_event = smcd_signal_ieq, + .move_data = smcd_move, + .get_system_eid = ism_get_seid, + .get_local_gid = smcd_get_local_gid, + .get_chid = smcd_get_chid, + .get_dev = smcd_get_dev, +}; + +const struct smcd_ops *ism_get_smcd_ops(void) +{ + return &ism_ops; +} +EXPORT_SYMBOL_GPL(ism_get_smcd_ops); +#endif diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 8bd9fd51208c..1d5b207c2b9e 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2801,9 +2801,11 @@ static void qeth_print_status_message(struct qeth_card *card) * of the level OSA sets the first character to zero * */ if (!card->info.mcl_level[0]) { - sprintf(card->info.mcl_level, "%02x%02x", - card->info.mcl_level[2], - card->info.mcl_level[3]); + scnprintf(card->info.mcl_level, + sizeof(card->info.mcl_level), + "%02x%02x", + card->info.mcl_level[2], + card->info.mcl_level[3]); break; } fallthrough; @@ -6090,7 +6092,7 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *fmt, ...) if (!debug_level_enabled(id, level)) return; va_start(args, fmt); - vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args); + vscnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args); va_end(args); debug_text_event(id, level, dbf_txt_buf); } @@ -6330,8 +6332,8 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev) goto err_dev; } - snprintf(dbf_name, sizeof(dbf_name), "qeth_card_%s", - dev_name(&gdev->dev)); + scnprintf(dbf_name, sizeof(dbf_name), "qeth_card_%s", + dev_name(&gdev->dev)); card->debug = qeth_get_dbf_entry(dbf_name); if (!card->debug) { rc = qeth_add_dbf_entry(card, dbf_name); diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index d1adc4b83193..eea93f8f106f 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -23,15 +23,15 @@ static ssize_t qeth_dev_state_show(struct device *dev, switch (card->state) { case CARD_STATE_DOWN: - return sprintf(buf, "DOWN\n"); + return sysfs_emit(buf, "DOWN\n"); case CARD_STATE_SOFTSETUP: if (card->dev->flags & IFF_UP) - return sprintf(buf, "UP (LAN %s)\n", - netif_carrier_ok(card->dev) ? "ONLINE" : - "OFFLINE"); - return sprintf(buf, "SOFTSETUP\n"); + return sysfs_emit(buf, "UP (LAN %s)\n", + netif_carrier_ok(card->dev) ? + "ONLINE" : "OFFLINE"); + return sysfs_emit(buf, "SOFTSETUP\n"); default: - return sprintf(buf, "UNKNOWN\n"); + return sysfs_emit(buf, "UNKNOWN\n"); } } @@ -42,7 +42,7 @@ static ssize_t qeth_dev_chpid_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%02X\n", card->info.chpid); + return sysfs_emit(buf, "%02X\n", card->info.chpid); } static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL); @@ -52,7 +52,7 @@ static ssize_t qeth_dev_if_name_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", netdev_name(card->dev)); + return sysfs_emit(buf, "%s\n", netdev_name(card->dev)); } static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL); @@ -62,7 +62,7 @@ static ssize_t qeth_dev_card_type_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", qeth_get_cardname_short(card)); + return sysfs_emit(buf, "%s\n", qeth_get_cardname_short(card)); } static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL); @@ -86,7 +86,7 @@ static ssize_t qeth_dev_inbuf_size_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", qeth_get_bufsize_str(card)); + return sysfs_emit(buf, "%s\n", qeth_get_bufsize_str(card)); } static DEVICE_ATTR(inbuf_size, 0444, qeth_dev_inbuf_size_show, NULL); @@ -96,7 +96,7 @@ static ssize_t qeth_dev_portno_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%i\n", card->dev->dev_port); + return sysfs_emit(buf, "%i\n", card->dev->dev_port); } static ssize_t qeth_dev_portno_store(struct device *dev, @@ -134,7 +134,7 @@ static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store); static ssize_t qeth_dev_portname_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "no portname required\n"); + return sysfs_emit(buf, "no portname required\n"); } static ssize_t qeth_dev_portname_store(struct device *dev, @@ -157,18 +157,18 @@ static ssize_t qeth_dev_prioqing_show(struct device *dev, switch (card->qdio.do_prio_queueing) { case QETH_PRIO_Q_ING_PREC: - return sprintf(buf, "%s\n", "by precedence"); + return sysfs_emit(buf, "%s\n", "by precedence"); case QETH_PRIO_Q_ING_TOS: - return sprintf(buf, "%s\n", "by type of service"); + return sysfs_emit(buf, "%s\n", "by type of service"); case QETH_PRIO_Q_ING_SKB: - return sprintf(buf, "%s\n", "by skb-priority"); + return sysfs_emit(buf, "%s\n", "by skb-priority"); case QETH_PRIO_Q_ING_VLAN: - return sprintf(buf, "%s\n", "by VLAN headers"); + return sysfs_emit(buf, "%s\n", "by VLAN headers"); case QETH_PRIO_Q_ING_FIXED: - return sprintf(buf, "always queue %i\n", + return sysfs_emit(buf, "always queue %i\n", card->qdio.default_out_queue); default: - return sprintf(buf, "disabled\n"); + return sysfs_emit(buf, "disabled\n"); } } @@ -242,7 +242,7 @@ static ssize_t qeth_dev_bufcnt_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count); + return sysfs_emit(buf, "%i\n", card->qdio.in_buf_pool.buf_count); } static ssize_t qeth_dev_bufcnt_store(struct device *dev, @@ -298,7 +298,7 @@ static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store); static ssize_t qeth_dev_performance_stats_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "1\n"); + return sysfs_emit(buf, "1\n"); } static ssize_t qeth_dev_performance_stats_store(struct device *dev, @@ -335,7 +335,7 @@ static ssize_t qeth_dev_layer2_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%i\n", card->options.layer); + return sysfs_emit(buf, "%i\n", card->options.layer); } static ssize_t qeth_dev_layer2_store(struct device *dev, @@ -470,23 +470,25 @@ static ssize_t qeth_dev_switch_attrs_show(struct device *dev, int rc = 0; if (!qeth_card_hw_is_reachable(card)) - return sprintf(buf, "n/a\n"); + return sysfs_emit(buf, "n/a\n"); rc = qeth_query_switch_attributes(card, &sw_info); if (rc) return rc; if (!sw_info.capabilities) - rc = sprintf(buf, "unknown"); + rc = sysfs_emit(buf, "unknown"); if (sw_info.capabilities & QETH_SWITCH_FORW_802_1) - rc = sprintf(buf, (sw_info.settings & QETH_SWITCH_FORW_802_1 ? - "[802.1]" : "802.1")); + rc = sysfs_emit(buf, + (sw_info.settings & QETH_SWITCH_FORW_802_1 ? + "[802.1]" : "802.1")); if (sw_info.capabilities & QETH_SWITCH_FORW_REFL_RELAY) - rc += sprintf(buf + rc, - (sw_info.settings & QETH_SWITCH_FORW_REFL_RELAY ? - " [rr]" : " rr")); - rc += sprintf(buf + rc, "\n"); + rc += sysfs_emit_at(buf, rc, + (sw_info.settings & + QETH_SWITCH_FORW_REFL_RELAY ? + " [rr]" : " rr")); + rc += sysfs_emit_at(buf, rc, "\n"); return rc; } @@ -573,7 +575,7 @@ static ssize_t qeth_dev_blkt_total_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%i\n", card->info.blkt.time_total); + return sysfs_emit(buf, "%i\n", card->info.blkt.time_total); } static ssize_t qeth_dev_blkt_total_store(struct device *dev, @@ -593,7 +595,7 @@ static ssize_t qeth_dev_blkt_inter_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%i\n", card->info.blkt.inter_packet); + return sysfs_emit(buf, "%i\n", card->info.blkt.inter_packet); } static ssize_t qeth_dev_blkt_inter_store(struct device *dev, @@ -613,7 +615,7 @@ static ssize_t qeth_dev_blkt_inter_jumbo_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%i\n", card->info.blkt.inter_packet_jumbo); + return sysfs_emit(buf, "%i\n", card->info.blkt.inter_packet_jumbo); } static ssize_t qeth_dev_blkt_inter_jumbo_store(struct device *dev, diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c index e250f49535fa..c1caf7734c3e 100644 --- a/drivers/s390/net/qeth_ethtool.c +++ b/drivers/s390/net/qeth_ethtool.c @@ -172,7 +172,7 @@ static void qeth_get_strings(struct net_device *dev, u32 stringset, u8 *data) qeth_add_stat_strings(&data, prefix, card_stats, CARD_STATS_LEN); for (i = 0; i < card->qdio.no_out_queues; i++) { - snprintf(prefix, ETH_GSTRING_LEN, "tx%u ", i); + scnprintf(prefix, ETH_GSTRING_LEN, "tx%u ", i); qeth_add_stat_strings(&data, prefix, txq_stats, TXQ_STATS_LEN); } @@ -192,8 +192,8 @@ static void qeth_get_drvinfo(struct net_device *dev, sizeof(info->driver)); strscpy(info->fw_version, card->info.mcl_level, sizeof(info->fw_version)); - snprintf(info->bus_info, sizeof(info->bus_info), "%s/%s/%s", - CARD_RDEV_ID(card), CARD_WDEV_ID(card), CARD_DDEV_ID(card)); + scnprintf(info->bus_info, sizeof(info->bus_info), "%s/%s/%s", + CARD_RDEV_ID(card), CARD_WDEV_ID(card), CARD_DDEV_ID(card)); } static void qeth_get_channels(struct net_device *dev, diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index c6ded3fdd715..9f13ed170a43 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -1255,37 +1255,38 @@ static void qeth_bridge_emit_host_event(struct qeth_card *card, switch (evtype) { case anev_reg_unreg: - snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=%s", - (code & IPA_ADDR_CHANGE_CODE_REMOVAL) - ? "deregister" : "register"); + scnprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=%s", + (code & IPA_ADDR_CHANGE_CODE_REMOVAL) + ? "deregister" : "register"); env[i] = str[i]; i++; if (code & IPA_ADDR_CHANGE_CODE_VLANID) { - snprintf(str[i], sizeof(str[i]), "VLAN=%d", - addr_lnid->lnid); + scnprintf(str[i], sizeof(str[i]), "VLAN=%d", + addr_lnid->lnid); env[i] = str[i]; i++; } if (code & IPA_ADDR_CHANGE_CODE_MACADDR) { - snprintf(str[i], sizeof(str[i]), "MAC=%pM", - addr_lnid->mac); + scnprintf(str[i], sizeof(str[i]), "MAC=%pM", + addr_lnid->mac); env[i] = str[i]; i++; } - snprintf(str[i], sizeof(str[i]), "NTOK_BUSID=%x.%x.%04x", - token->cssid, token->ssid, token->devnum); + scnprintf(str[i], sizeof(str[i]), "NTOK_BUSID=%x.%x.%04x", + token->cssid, token->ssid, token->devnum); env[i] = str[i]; i++; - snprintf(str[i], sizeof(str[i]), "NTOK_IID=%02x", token->iid); + scnprintf(str[i], sizeof(str[i]), "NTOK_IID=%02x", token->iid); env[i] = str[i]; i++; - snprintf(str[i], sizeof(str[i]), "NTOK_CHPID=%02x", - token->chpid); + scnprintf(str[i], sizeof(str[i]), "NTOK_CHPID=%02x", + token->chpid); env[i] = str[i]; i++; - snprintf(str[i], sizeof(str[i]), "NTOK_CHID=%04x", token->chid); + scnprintf(str[i], sizeof(str[i]), "NTOK_CHID=%04x", + token->chid); env[i] = str[i]; i++; break; case anev_abort: - snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=abort"); + scnprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=abort"); env[i] = str[i]; i++; break; case anev_reset: - snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=reset"); + scnprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=reset"); env[i] = str[i]; i++; break; } @@ -1314,17 +1315,17 @@ static void qeth_bridge_state_change_worker(struct work_struct *work) NULL }; - snprintf(env_locrem, sizeof(env_locrem), "BRIDGEPORT=statechange"); - snprintf(env_role, sizeof(env_role), "ROLE=%s", - (data->role == QETH_SBP_ROLE_NONE) ? "none" : - (data->role == QETH_SBP_ROLE_PRIMARY) ? "primary" : - (data->role == QETH_SBP_ROLE_SECONDARY) ? "secondary" : - "<INVALID>"); - snprintf(env_state, sizeof(env_state), "STATE=%s", - (data->state == QETH_SBP_STATE_INACTIVE) ? "inactive" : - (data->state == QETH_SBP_STATE_STANDBY) ? "standby" : - (data->state == QETH_SBP_STATE_ACTIVE) ? "active" : - "<INVALID>"); + scnprintf(env_locrem, sizeof(env_locrem), "BRIDGEPORT=statechange"); + scnprintf(env_role, sizeof(env_role), "ROLE=%s", + (data->role == QETH_SBP_ROLE_NONE) ? "none" : + (data->role == QETH_SBP_ROLE_PRIMARY) ? "primary" : + (data->role == QETH_SBP_ROLE_SECONDARY) ? "secondary" : + "<INVALID>"); + scnprintf(env_state, sizeof(env_state), "STATE=%s", + (data->state == QETH_SBP_STATE_INACTIVE) ? "inactive" : + (data->state == QETH_SBP_STATE_STANDBY) ? "standby" : + (data->state == QETH_SBP_STATE_ACTIVE) ? "active" : + "<INVALID>"); kobject_uevent_env(&data->card->gdev->dev.kobj, KOBJ_CHANGE, env); kfree(data); diff --git a/drivers/s390/net/qeth_l2_sys.c b/drivers/s390/net/qeth_l2_sys.c index a617351fff57..7f592f912517 100644 --- a/drivers/s390/net/qeth_l2_sys.c +++ b/drivers/s390/net/qeth_l2_sys.c @@ -19,7 +19,7 @@ static ssize_t qeth_bridge_port_role_state_show(struct device *dev, char *word; if (!qeth_bridgeport_allowed(card)) - return sprintf(buf, "n/a (VNIC characteristics)\n"); + return sysfs_emit(buf, "n/a (VNIC characteristics)\n"); mutex_lock(&card->sbp_lock); if (qeth_card_hw_is_reachable(card) && @@ -53,7 +53,7 @@ static ssize_t qeth_bridge_port_role_state_show(struct device *dev, QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x", card->options.sbp.role, state); else - rc = sprintf(buf, "%s\n", word); + rc = sysfs_emit(buf, "%s\n", word); } mutex_unlock(&card->sbp_lock); @@ -66,7 +66,7 @@ static ssize_t qeth_bridge_port_role_show(struct device *dev, struct qeth_card *card = dev_get_drvdata(dev); if (!qeth_bridgeport_allowed(card)) - return sprintf(buf, "n/a (VNIC characteristics)\n"); + return sysfs_emit(buf, "n/a (VNIC characteristics)\n"); return qeth_bridge_port_role_state_show(dev, attr, buf, 0); } @@ -117,7 +117,7 @@ static ssize_t qeth_bridge_port_state_show(struct device *dev, struct qeth_card *card = dev_get_drvdata(dev); if (!qeth_bridgeport_allowed(card)) - return sprintf(buf, "n/a (VNIC characteristics)\n"); + return sysfs_emit(buf, "n/a (VNIC characteristics)\n"); return qeth_bridge_port_role_state_show(dev, attr, buf, 1); } @@ -132,11 +132,11 @@ static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev, int enabled; if (!qeth_bridgeport_allowed(card)) - return sprintf(buf, "n/a (VNIC characteristics)\n"); + return sysfs_emit(buf, "n/a (VNIC characteristics)\n"); enabled = card->options.sbp.hostnotification; - return sprintf(buf, "%d\n", enabled); + return sysfs_emit(buf, "%d\n", enabled); } static ssize_t qeth_bridgeport_hostnotification_store(struct device *dev, @@ -180,7 +180,7 @@ static ssize_t qeth_bridgeport_reflect_show(struct device *dev, char *state; if (!qeth_bridgeport_allowed(card)) - return sprintf(buf, "n/a (VNIC characteristics)\n"); + return sysfs_emit(buf, "n/a (VNIC characteristics)\n"); if (card->options.sbp.reflect_promisc) { if (card->options.sbp.reflect_promisc_primary) @@ -190,7 +190,7 @@ static ssize_t qeth_bridgeport_reflect_show(struct device *dev, } else state = "none"; - return sprintf(buf, "%s\n", state); + return sysfs_emit(buf, "%s\n", state); } static ssize_t qeth_bridgeport_reflect_store(struct device *dev, @@ -280,10 +280,10 @@ static ssize_t qeth_vnicc_timeout_show(struct device *dev, rc = qeth_l2_vnicc_get_timeout(card, &timeout); if (rc == -EBUSY) - return sprintf(buf, "n/a (BridgePort)\n"); + return sysfs_emit(buf, "n/a (BridgePort)\n"); if (rc == -EOPNOTSUPP) - return sprintf(buf, "n/a\n"); - return rc ? rc : sprintf(buf, "%d\n", timeout); + return sysfs_emit(buf, "n/a\n"); + return rc ? rc : sysfs_emit(buf, "%d\n", timeout); } /* change timeout setting */ @@ -318,10 +318,10 @@ static ssize_t qeth_vnicc_char_show(struct device *dev, rc = qeth_l2_vnicc_get_state(card, vnicc, &state); if (rc == -EBUSY) - return sprintf(buf, "n/a (BridgePort)\n"); + return sysfs_emit(buf, "n/a (BridgePort)\n"); if (rc == -EOPNOTSUPP) - return sprintf(buf, "n/a\n"); - return rc ? rc : sprintf(buf, "%d\n", state); + return sysfs_emit(buf, "n/a\n"); + return rc ? rc : sysfs_emit(buf, "%d\n", state); } /* change setting of characteristic */ diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index d8487a10cd55..af4e60d2917e 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -19,6 +19,7 @@ #include <linux/etherdevice.h> #include <linux/ip.h> #include <linux/in.h> +#include <linux/inet.h> #include <linux/ipv6.h> #include <linux/inetdevice.h> #include <linux/igmp.h> @@ -46,9 +47,9 @@ int qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const u8 *addr, char *buf) { if (proto == QETH_PROT_IPV4) - return sprintf(buf, "%pI4", addr); + return scnprintf(buf, INET_ADDRSTRLEN, "%pI4", addr); else - return sprintf(buf, "%pI6", addr); + return scnprintf(buf, INET6_ADDRSTRLEN, "%pI6", addr); } static struct qeth_ipaddr *qeth_l3_find_addr_by_ip(struct qeth_card *card, @@ -158,7 +159,7 @@ static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) { int rc = 0; struct qeth_ipaddr *addr; - char buf[40]; + char buf[INET6_ADDRSTRLEN]; if (tmp_addr->type == QETH_IP_TYPE_RXIP) QETH_CARD_TEXT(card, 2, "addrxip"); diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 1082380b21f8..9f90a860ca2c 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -32,26 +32,26 @@ static ssize_t qeth_l3_dev_route_show(struct qeth_card *card, { switch (route->type) { case PRIMARY_ROUTER: - return sprintf(buf, "%s\n", "primary router"); + return sysfs_emit(buf, "%s\n", "primary router"); case SECONDARY_ROUTER: - return sprintf(buf, "%s\n", "secondary router"); + return sysfs_emit(buf, "%s\n", "secondary router"); case MULTICAST_ROUTER: if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) - return sprintf(buf, "%s\n", "multicast router+"); + return sysfs_emit(buf, "%s\n", "multicast router+"); else - return sprintf(buf, "%s\n", "multicast router"); + return sysfs_emit(buf, "%s\n", "multicast router"); case PRIMARY_CONNECTOR: if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) - return sprintf(buf, "%s\n", "primary connector+"); + return sysfs_emit(buf, "%s\n", "primary connector+"); else - return sprintf(buf, "%s\n", "primary connector"); + return sysfs_emit(buf, "%s\n", "primary connector"); case SECONDARY_CONNECTOR: if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) - return sprintf(buf, "%s\n", "secondary connector+"); + return sysfs_emit(buf, "%s\n", "secondary connector+"); else - return sprintf(buf, "%s\n", "secondary connector"); + return sysfs_emit(buf, "%s\n", "secondary connector"); default: - return sprintf(buf, "%s\n", "no"); + return sysfs_emit(buf, "%s\n", "no"); } } @@ -138,7 +138,7 @@ static ssize_t qeth_l3_dev_sniffer_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%i\n", card->options.sniffer ? 1 : 0); + return sysfs_emit(buf, "%i\n", card->options.sniffer ? 1 : 0); } static ssize_t qeth_l3_dev_sniffer_store(struct device *dev, @@ -200,7 +200,7 @@ static ssize_t qeth_l3_dev_hsuid_show(struct device *dev, memcpy(tmp_hsuid, card->options.hsuid, sizeof(tmp_hsuid)); EBCASC(tmp_hsuid, 8); - return sprintf(buf, "%s\n", tmp_hsuid); + return sysfs_emit(buf, "%s\n", tmp_hsuid); } static ssize_t qeth_l3_dev_hsuid_store(struct device *dev, @@ -252,8 +252,8 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev, goto out; } - snprintf(card->options.hsuid, sizeof(card->options.hsuid), - "%-8s", tmp); + scnprintf(card->options.hsuid, sizeof(card->options.hsuid), + "%-8s", tmp); ASCEBC(card->options.hsuid, 8); memcpy(card->dev->perm_addr, card->options.hsuid, 9); @@ -285,7 +285,7 @@ static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", card->ipato.enabled ? 1 : 0); + return sysfs_emit(buf, "%u\n", card->ipato.enabled ? 1 : 0); } static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev, @@ -330,7 +330,7 @@ static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", card->ipato.invert4 ? 1 : 0); + return sysfs_emit(buf, "%u\n", card->ipato.invert4 ? 1 : 0); } static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev, @@ -367,35 +367,21 @@ static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card, enum qeth_prot_versions proto) { struct qeth_ipato_entry *ipatoe; - int str_len = 0; + char addr_str[INET6_ADDRSTRLEN]; + int offset = 0; mutex_lock(&card->ip_lock); list_for_each_entry(ipatoe, &card->ipato.entries, entry) { - char addr_str[40]; - int entry_len; - if (ipatoe->proto != proto) continue; - entry_len = qeth_l3_ipaddr_to_string(proto, ipatoe->addr, - addr_str); - if (entry_len < 0) - continue; - - /* Append /%mask to the entry: */ - entry_len += 1 + ((proto == QETH_PROT_IPV4) ? 2 : 3); - /* Enough room to format %entry\n into null terminated page? */ - if (entry_len + 1 > PAGE_SIZE - str_len - 1) - break; - - entry_len = scnprintf(buf, PAGE_SIZE - str_len, - "%s/%i\n", addr_str, ipatoe->mask_bits); - str_len += entry_len; - buf += entry_len; + qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str); + offset += sysfs_emit_at(buf, offset, "%s/%i\n", + addr_str, ipatoe->mask_bits); } mutex_unlock(&card->ip_lock); - return str_len ? str_len : scnprintf(buf, PAGE_SIZE, "\n"); + return offset ? offset : sysfs_emit(buf, "\n"); } static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev, @@ -413,7 +399,7 @@ static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto, int rc; /* Expected input pattern: %addr/%mask */ - sep = strnchr(buf, 40, '/'); + sep = strnchr(buf, INET6_ADDRSTRLEN, '/'); if (!sep) return -EINVAL; @@ -501,7 +487,7 @@ static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", card->ipato.invert6 ? 1 : 0); + return sysfs_emit(buf, "%u\n", card->ipato.invert6 ? 1 : 0); } static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev, @@ -586,35 +572,22 @@ static ssize_t qeth_l3_dev_ip_add_show(struct device *dev, char *buf, enum qeth_ip_types type) { struct qeth_card *card = dev_get_drvdata(dev); + char addr_str[INET6_ADDRSTRLEN]; struct qeth_ipaddr *ipaddr; - int str_len = 0; + int offset = 0; int i; mutex_lock(&card->ip_lock); hash_for_each(card->ip_htable, i, ipaddr, hnode) { - char addr_str[40]; - int entry_len; - if (ipaddr->proto != proto || ipaddr->type != type) continue; - entry_len = qeth_l3_ipaddr_to_string(proto, (u8 *)&ipaddr->u, - addr_str); - if (entry_len < 0) - continue; - - /* Enough room to format %addr\n into null terminated page? */ - if (entry_len + 1 > PAGE_SIZE - str_len - 1) - break; - - entry_len = scnprintf(buf, PAGE_SIZE - str_len, "%s\n", - addr_str); - str_len += entry_len; - buf += entry_len; + qeth_l3_ipaddr_to_string(proto, (u8 *)&ipaddr->u, addr_str); + offset += sysfs_emit_at(buf, offset, "%s\n", addr_str); } mutex_unlock(&card->ip_lock); - return str_len ? str_len : scnprintf(buf, PAGE_SIZE, "\n"); + return offset ? offset : sysfs_emit(buf, "\n"); } static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev, |