* [PATCH] net: do not call sock_put() on TIMEWAIT sockets
From: Eric Dumazet @ 2013-10-02 4:04 UTC (permalink / raw)
To: David Miller; +Cc: netdev
From: Eric Dumazet <edumazet@google.com>
commit 3ab5aee7fe84 ("net: Convert TCP & DCCP hash tables to use RCU /
hlist_nulls") incorrectly used sock_put() on TIMEWAIT sockets.
We should instead use inet_twsk_put()
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/ipv4/inet_hashtables.c | 2 +-
net/ipv6/inet6_hashtables.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 7bd8983..96da9c7 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -287,7 +287,7 @@ begintw:
if (unlikely(!INET_TW_MATCH(sk, net, acookie,
saddr, daddr, ports,
dif))) {
- sock_put(sk);
+ inet_twsk_put(inet_twsk(sk));
goto begintw;
}
goto out;
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 32b4a16..066640e 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -116,7 +116,7 @@ begintw:
}
if (unlikely(!INET6_TW_MATCH(sk, net, saddr, daddr,
ports, dif))) {
- sock_put(sk);
+ inet_twsk_put(inet_twsk(sk));
goto begintw;
}
goto out;
^ permalink raw reply related
* [PATCH v2 net-next] include/linux/skbuff.h: move CONFIG_XFRM check inside the skb_sec_path()
From: Denis Kirjanov @ 2013-10-02 1:58 UTC (permalink / raw)
To: netdev, davem; +Cc: Denis Kirjanov
And thus we have only one function definition
Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
---
v1->v2: rebase to net-next head
---
include/linux/skbuff.h | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 71b1d94..1cd32f9 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2708,17 +2708,14 @@ static inline bool skb_rx_queue_recorded(const struct sk_buff *skb)
u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb,
unsigned int num_tx_queues);
-#ifdef CONFIG_XFRM
static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
{
+#ifdef CONFIG_XFRM
return skb->sp;
-}
#else
-static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
-{
return NULL;
-}
#endif
+}
/* Keeps track of mac header offset relative to skb->head.
* It is useful for TSO of Tunneling protocol. e.g. GRE.
--
1.8.0.2
^ permalink raw reply related
* Re: [PATCH] can: add Renesas R-Car CAN driver
From: Wolfgang Grandegger @ 2013-10-02 6:09 UTC (permalink / raw)
To: Sergei Shtylyov, netdev, mkl, linux-can; +Cc: linux-sh
In-Reply-To: <201309280211.39068.sergei.shtylyov@cogentembedded.com>
Hallo Sergei,
thanks for your contribution. The patch looks already quite good. Before
I find time for a detailed review could you please check error handling
and bus-off recovery by reporting the output of "$ candump -td -e
any,0:0,#FFFFFFFF" while sending messages to the device ...
1. ... without cable connected
2. ... with short-circuited CAN high and low and doing some time later
a manual recovery with "ip link set can0 type can restart"
I also wonder if the messages are always sent in order. You could use
the program "canfdtest" [1] from the can-utils for validation.
Support for CAN_CTRLMODE_BERR_REPORTING would also be nice, especially
if the bus errors reporting can easily be switched off (via interrupt mask).
There is also the RCAN-TL1 (Renesas CAN Time Trigger Level 1) module
e.g. available on the SH7203 Group of processors. Is this CAN controller
compatible to some extend with the R-Car CAN or a completely different
implementation?
[1] https://gitorious.org/linux-can/can-utils/source/canfdtest.c
Wolfgang.
On 09/28/2013 12:11 AM, Sergei Shtylyov wrote:
> Add support for the CAN controller found in Renesas R-Car SoCs.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>
> ---
> The patch is against the 'linux-can-next.git' repo.
>
> drivers/net/can/Kconfig | 9
> drivers/net/can/Makefile | 1
> drivers/net/can/rcar_can.c | 898 ++++++++++++++++++++++++++++++++++
> include/linux/can/platform/rcar_can.h | 15
> 4 files changed, 923 insertions(+)
>
> Index: linux-can-next/drivers/net/can/Kconfig
> ===================================================================
> --- linux-can-next.orig/drivers/net/can/Kconfig
> +++ linux-can-next/drivers/net/can/Kconfig
> @@ -125,6 +125,15 @@ config CAN_GRCAN
> endian syntheses of the cores would need some modifications on
> the hardware level to work.
>
> +config CAN_RCAR
> + tristate "Renesas R-Car CAN controller"
> + ---help---
> + Say Y here if you want to use CAN controller found on Renesas R-Car
> + SoCs.
> +
> + To compile this driver as a module, choose M here: the module will
> + be called rcar_can.
> +
> source "drivers/net/can/mscan/Kconfig"
>
> source "drivers/net/can/sja1000/Kconfig"
> Index: linux-can-next/drivers/net/can/Makefile
> ===================================================================
> --- linux-can-next.orig/drivers/net/can/Makefile
> +++ linux-can-next/drivers/net/can/Makefile
> @@ -25,5 +25,6 @@ obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ica
> obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o
> obj-$(CONFIG_PCH_CAN) += pch_can.o
> obj-$(CONFIG_CAN_GRCAN) += grcan.o
> +obj-$(CONFIG_CAN_RCAR) += rcar_can.o
>
> ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
> Index: linux-can-next/drivers/net/can/rcar_can.c
> ===================================================================
> --- /dev/null
> +++ linux-can-next/drivers/net/can/rcar_can.c
> @@ -0,0 +1,898 @@
> +/*
> + * Renesas R-Car CAN device driver
> + *
> + * Copyright (C) 2013 Cogent Embedded, Inc. <source@cogentembedded.com>
> + * Copyright (C) 2013 Renesas Solutions Corp.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/interrupt.h>
> +#include <linux/errno.h>
> +#include <linux/netdevice.h>
> +#include <linux/platform_device.h>
> +#include <linux/can/led.h>
> +#include <linux/can/dev.h>
> +#include <linux/clk.h>
> +#include <linux/can/platform/rcar_can.h>
> +
> +#define DRV_NAME "rcar_can"
> +
> +#define RCAR_CAN_MIER1 0x42C /* CANi Mailbox Interrupt Enable Register 1 */
> +#define RCAR_CAN_MKR(n) ((n) < 2 ? 0x430 + 4 * (n) : 0x400 + 4 * ((n) - 2))
> + /* CANi Mask Register */
> +#define RCAR_CAN_MKIVLR0 0x438 /* CANi Mask Invalid Register 0 */
> +#define RCAR_CAN_MIER0 0x43C /* CANi Mailbox Interrupt Enable Register 0 */
> +
> +#define RCAR_CAN_MCTL(n) (0x800 + (n)) /* CANi Message Control Register */
> +#define RCAR_CAN_CTLR 0x840 /* CANi Control Register */
> +#define RCAR_CAN_STR 0x842 /* CANi Status Register */
> +#define RCAR_CAN_BCR 0x844 /* CANi Bit Configuration Register */
> +#define RCAR_CAN_CLKR 0x847 /* CANi Clock Select Register */
> +#define RCAR_CAN_EIER 0x84C /* CANi Error Interrupt Enable Register */
> +#define RCAR_CAN_EIFR 0x84D /* CANi Err Interrupt Factor Judge Register */
> +#define RCAR_CAN_RECR 0x84E /* CANi Receive Error Count Register */
> +#define RCAR_CAN_TECR 0x84F /* CANi Transmit Error Count Register */
> +#define RCAR_CAN_ECSR 0x850 /* CANi Error Code Store Register */
> +#define RCAR_CAN_MSSR 0x852 /* CANi Mailbox Search Status Register */
> +#define RCAR_CAN_MSMR 0x853 /* CANi Mailbox Search Mode Register */
> +#define RCAR_CAN_TCR 0x858 /* CANi Test Control Register */
> +#define RCAR_CAN_IER 0x860 /* CANi Interrupt Enable Register */
> +#define RCAR_CAN_ISR 0x861 /* CANi Interrupt Status Register */
> +
> +/* Offsets of RCAR_CAN Mailbox Registers */
> +#define MBX_HDR_OFFSET 0x0
> +#define MBX_DLC_OFFSET 0x5
> +#define MBX_DATA_OFFSET 0x6
> +
> +#define RCAR_CAN_MBX_SIZE 0x10
> +
> +/* Control Register bits */
> +#define CTLR_SLPM BIT(10)
> +#define CTLR_HALT BIT(9)
> +#define CTLR_RESET BIT(8)
> +#define CTLR_FORCE_RESET (3 << 8)
> +#define CTLR_TPM BIT(4) /* Transmission Priority Mode Select Bit */
> +#define CTLR_IDFM_MIXED BIT(2) /* Mixed ID mode */
> +
> +/* Message Control Register bits */
> +#define MCTL_TRMREQ BIT(7)
> +#define MCTL_RECREQ BIT(6)
> +#define MCTL_ONESHOT BIT(4)
> +#define MCTL_SENTDATA BIT(0)
> +#define MCTL_NEWDATA BIT(0)
> +
> +#define N_RX_MKREGS 2 /* Number of mask registers */
> + /* for Rx mailboxes 0-31 */
> +
> +/* Bit Configuration Register settings */
> +#define BCR_TSEG1(x) (((x) & 0x0f) << 28)
> +#define BCR_BPR(x) (((x) & 0x3ff) << 16)
> +#define BCR_SJW(x) (((x) & 0x3) << 12)
> +#define BCR_TSEG2(x) (((x) & 0x07) << 8)
> +
> +/* Mailbox and Mask Registers bits */
> +#define RCAR_CAN_IDE BIT(31)
> +#define RCAR_CAN_RTR BIT(30)
> +#define RCAR_CAN_SID_SHIFT 18
> +
> +/* Interrupt Enable Register bits */
> +#define IER_ERSIE BIT(5) /* Error (ERS) Interrupt Enable Bit */
> +#define IER_RXM0IE BIT(2) /* Mailbox 0 Successful Reception (RXM0) */
> + /* Interrupt Enable Bit */
> +#define IER_RXM1IE BIT(1) /* Mailbox 1 Successful Reception (RXM0) */
> + /* Interrupt Enable Bit */
> +#define IER_TXMIE BIT(0) /* Mailbox 32 to 63 Successful Tx */
> + /* Interrupt Enable Bit */
> +
> +/* Interrupt Status Register bits */
> +#define ISR_ERSF BIT(5) /* Error (ERS) Interrupt Status Bit */
> +#define ISR_RXM0F BIT(2) /* Mailbox 0 Successful Reception (RXM0) */
> + /* Interrupt Status Bit */
> +#define ISR_RXM1F BIT(1) /* Mailbox 1 to 63 Successful Reception */
> + /* (RXM1) Interrupt Status Bit */
> +#define ISR_TXMF BIT(0) /* Mailbox 32 to 63 Successful Transmission */
> + /* (TXM) Interrupt Status Bit */
> +
> +/* Error Interrupt Enable Register bits */
> +#define EIER_BLIE BIT(7) /* Bus Lock Interrupt Enable */
> +#define EIER_OLIE BIT(6) /* Overload Frame Transmit Interrupt Enable */
> +#define EIER_ORIE BIT(5) /* Receive Overrun Interrupt Enable */
> +#define EIER_BORIE BIT(4) /* Bus-Off Recovery Interrupt Enable */
> +
> +#define EIER_BOEIE BIT(3) /* Bus-Off Entry Interrupt Enable */
> +#define EIER_EPIE BIT(2) /* Error Passive Interrupt Enable */
> +#define EIER_EWIE BIT(1) /* Error Warning Interrupt Enable */
> +#define EIER_BEIE BIT(0) /* Bus Error Interrupt Enable */
> +
> +/* Error Interrupt Factor Judge Register bits */
> +#define EIFR_BLIF BIT(7) /* Bus Lock Detect Flag */
> +#define EIFR_OLIF BIT(6) /* Overload Frame Transmission Detect Flag */
> +#define EIFR_ORIF BIT(5) /* Receive Overrun Detect Flag */
> +#define EIFR_BORIF BIT(4) /* Bus-Off Recovery Detect Flag */
> +#define EIFR_BOEIF BIT(3) /* Bus-Off Entry Detect Flag */
> +#define EIFR_EPIF BIT(2) /* Error Passive Detect Flag */
> +#define EIFR_EWIF BIT(1) /* Error Warning Detect Flag */
> +#define EIFR_BEIF BIT(0) /* Bus Error Detect Flag */
> +
> +/* Error Code Store Register bits */
> +#define ECSR_EDPM BIT(7) /* Error Display Mode Select Bit */
> +#define ECSR_ADEF BIT(6) /* ACK Delimiter Error Flag */
> +#define ECSR_BE0F BIT(5) /* Bit Error (dominant) Flag */
> +#define ECSR_BE1F BIT(4) /* Bit Error (recessive) Flag */
> +#define ECSR_CEF BIT(3) /* CRC Error Flag */
> +#define ECSR_AEF BIT(2) /* ACK Error Flag */
> +#define ECSR_FEF BIT(1) /* Form Error Flag */
> +#define ECSR_SEF BIT(0) /* Stuff Error Flag */
> +
> +/* Mailbox Search Status Register bits */
> +#define MSSR_SEST BIT(7) /* Search Result Status Bit */
> +#define MSSR_MBNST 0x3f /* Search Result Mailbox Number Status mask */
> +
> +/* Mailbox Search Mode Register values */
> +#define MSMR_TXMB 1 /* Transmit mailbox search mode */
> +#define MSMR_RXMB 0 /* Receive mailbox search mode */
> +
> +/* Mailbox configuration:
> + * mailbox 0 - not used
> + * mailbox 1-31 - Rx
> + * mailbox 32-63 - Tx
> + * no FIFO mailboxes
> + */
> +#define N_MBX 64
> +#define FIRST_TX_MB 32
> +#define RX_MBX_MASK 0xFFFFFFFE
> +
> +#define RCAR_CAN_NAPI_WEIGHT (FIRST_TX_MB - 1)
> +
> +struct rcar_can_priv {
> + struct can_priv can; /* Must be the first member! */
> + struct net_device *ndev;
> + struct napi_struct napi;
> + void __iomem *reg_base;
> + struct clk *clk;
> + spinlock_t mier_lock;
> + u8 clock_select;
> +};
> +
> +static const struct can_bittiming_const rcar_can_bittiming_const = {
> + .name = DRV_NAME,
> + .tseg1_min = 4,
> + .tseg1_max = 16,
> + .tseg2_min = 2,
> + .tseg2_max = 8,
> + .sjw_max = 4,
> + .brp_min = 1,
> + .brp_max = 1024,
> + .brp_inc = 1,
> +};
> +
> +static inline u32 rcar_can_readl(struct rcar_can_priv *priv, int reg)
> +{
> + return readl(priv->reg_base + reg);
> +}
> +
> +static inline u16 rcar_can_readw(struct rcar_can_priv *priv, int reg)
> +{
> + return readw(priv->reg_base + reg);
> +}
> +
> +static inline u8 rcar_can_readb(struct rcar_can_priv *priv, int reg)
> +{
> + return readb(priv->reg_base + reg);
> +}
> +
> +static inline void rcar_can_writel(struct rcar_can_priv *priv, int reg, u32 val)
> +{
> + writel(val, priv->reg_base + reg);
> +}
> +
> +static inline void rcar_can_writew(struct rcar_can_priv *priv, int reg, u16 val)
> +{
> + writew(val, priv->reg_base + reg);
> +}
> +
> +static inline void rcar_can_writeb(struct rcar_can_priv *priv, int reg, u8 val)
> +{
> + writeb(val, priv->reg_base + reg);
> +}
> +
> +static inline u32 rcar_can_mbx_readl(struct rcar_can_priv *priv,
> + u32 mbxno, u8 offset)
> +{
> + return rcar_can_readl(priv, RCAR_CAN_MBX_SIZE * mbxno + offset);
> +}
> +
> +static inline u8 rcar_can_mbx_readb(struct rcar_can_priv *priv,
> + u32 mbxno, u8 offset)
> +{
> + return rcar_can_readb(priv, RCAR_CAN_MBX_SIZE * mbxno + offset);
> +}
> +
> +static inline void rcar_can_mbx_writel(struct rcar_can_priv *priv, u32 mbxno,
> + u8 offset, u32 val)
> +{
> + rcar_can_writel(priv, RCAR_CAN_MBX_SIZE * mbxno + offset, val);
> +}
> +
> +static inline void rcar_can_mbx_writeb(struct rcar_can_priv *priv, u32 mbxno,
> + u8 offset, u8 val)
> +{
> + rcar_can_writeb(priv, RCAR_CAN_MBX_SIZE * mbxno + offset, val);
> +}
> +
> +static void rcar_can_error(struct net_device *ndev)
> +{
> + struct rcar_can_priv *priv = netdev_priv(ndev);
> + struct net_device_stats *stats = &ndev->stats;
> + struct can_frame *cf;
> + struct sk_buff *skb;
> + u8 eifr;
> +
> + /* Propagate the error condition to the CAN stack */
> + skb = alloc_can_err_skb(ndev, &cf);
> + if (!skb) {
> + if (printk_ratelimit())
> + netdev_err(priv->ndev,
> + "%s: alloc_can_err_skb() failed\n",
> + __func__);
> + return;
> + }
> +
> + eifr = rcar_can_readb(priv, RCAR_CAN_EIFR);
> + if (eifr & EIFR_EWIF) {
> + netdev_dbg(priv->ndev, "Error warning interrupt\n");
> + priv->can.state = CAN_STATE_ERROR_WARNING;
> + priv->can.can_stats.error_warning++;
> + cf->can_id |= CAN_ERR_CRTL;
> + if (rcar_can_readb(priv, RCAR_CAN_TECR) > 96)
> + cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
> + if (rcar_can_readb(priv, RCAR_CAN_RECR) > 96)
> + cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
> + /* Clear interrupt condition */
> + rcar_can_writeb(priv, RCAR_CAN_EIFR, (u8)~EIFR_EWIF);
> + }
> + if (eifr & EIFR_EPIF) {
> + netdev_dbg(priv->ndev, "Error passive interrupt\n");
> + priv->can.state = CAN_STATE_ERROR_PASSIVE;
> + priv->can.can_stats.error_passive++;
> + cf->can_id |= CAN_ERR_CRTL;
> + if (rcar_can_readb(priv, RCAR_CAN_TECR) > 127)
> + cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
> + if (rcar_can_readb(priv, RCAR_CAN_RECR) > 127)
> + cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
> + /* Clear interrupt condition */
> + rcar_can_writeb(priv, RCAR_CAN_EIFR, (u8)~EIFR_EPIF);
> + }
> + if (eifr & EIFR_BOEIF) {
> + netdev_dbg(priv->ndev, "Bus-off entry interrupt\n");
> + priv->can.state = CAN_STATE_BUS_OFF;
> + cf->can_id |= CAN_ERR_BUSOFF;
> + /* Clear interrupt condition */
> + rcar_can_writeb(priv, RCAR_CAN_EIFR, (u8)~EIFR_BOEIF);
> + /* Disable all interrupts in bus-off to avoid int hog */
> + rcar_can_writeb(priv, RCAR_CAN_EIER, 0);
> + rcar_can_writeb(priv, RCAR_CAN_IER, 0);
> + can_bus_off(ndev);
> + }
> + if (eifr & EIFR_BEIF) {
> + int rx_errors = 0, tx_errors = 0, bus_errors = 0;
> + u8 ecsr;
> +
> + netdev_dbg(priv->ndev, "Bus error interrupt:\n");
> + cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
> + cf->data[2] = CAN_ERR_PROT_UNSPEC;
> +
> + ecsr = rcar_can_readb(priv, RCAR_CAN_ECSR);
> + if (ecsr & ECSR_ADEF) {
> + netdev_dbg(priv->ndev, "ACK Delimiter Error\n");
> + cf->data[3] |= CAN_ERR_PROT_LOC_ACK_DEL;
> + bus_errors++;
> + tx_errors++;
> + rcar_can_writeb(priv, RCAR_CAN_ECSR, (u8)~ECSR_ADEF);
> + }
> + if (ecsr & ECSR_BE0F) {
> + netdev_dbg(priv->ndev, "Bit Error (dominant)\n");
> + cf->data[2] |= CAN_ERR_PROT_BIT0;
> + bus_errors++;
> + tx_errors++;
> + rcar_can_writeb(priv, RCAR_CAN_ECSR, (u8)~ECSR_BE0F);
> + }
> + if (ecsr & ECSR_BE1F) {
> + netdev_dbg(priv->ndev, "Bit Error (recessive)\n");
> + cf->data[2] |= CAN_ERR_PROT_BIT1;
> + bus_errors++;
> + tx_errors++;
> + rcar_can_writeb(priv, RCAR_CAN_ECSR, (u8)~ECSR_BE1F);
> + }
> + if (ecsr & ECSR_CEF) {
> + netdev_dbg(priv->ndev, "CRC Error\n");
> + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
> + bus_errors++;
> + rx_errors++;
> + rcar_can_writeb(priv, RCAR_CAN_ECSR, (u8)~ECSR_CEF);
> + }
> + if (ecsr & ECSR_AEF) {
> + netdev_dbg(priv->ndev, "ACK Error\n");
> + cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
> + bus_errors++;
> + tx_errors++;
> + rcar_can_writeb(priv, RCAR_CAN_ECSR, (u8)~ECSR_AEF);
> + }
> + if (ecsr & ECSR_FEF) {
> + netdev_dbg(priv->ndev, "Form Error\n");
> + cf->data[2] |= CAN_ERR_PROT_FORM;
> + bus_errors++;
> + rx_errors++;
> + rcar_can_writeb(priv, RCAR_CAN_ECSR, (u8)~ECSR_FEF);
> + }
> + if (ecsr & ECSR_SEF) {
> + netdev_dbg(priv->ndev, "Stuff Error\n");
> + cf->data[2] |= CAN_ERR_PROT_STUFF;
> + bus_errors++;
> + rx_errors++;
> + rcar_can_writeb(priv, RCAR_CAN_ECSR, (u8)~ECSR_SEF);
> + }
> +
> + priv->can.can_stats.bus_error += bus_errors;
> + ndev->stats.rx_errors += rx_errors;
> + ndev->stats.tx_errors += tx_errors;
> + rcar_can_writeb(priv, RCAR_CAN_EIFR, (u8)~EIFR_BEIF);
> + }
> + if (eifr & EIFR_ORIF) {
> + netdev_dbg(priv->ndev, "Receive overrun error interrupt\n");
> + cf->can_id |= CAN_ERR_CRTL;
> + cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
> + ndev->stats.rx_over_errors++;
> + ndev->stats.rx_errors++;
> + rcar_can_writeb(priv, RCAR_CAN_EIFR, (u8)~EIFR_ORIF);
> + }
> + if (eifr & EIFR_OLIF) {
> + netdev_dbg(priv->ndev,
> + "Overload Frame Transmission error interrupt\n");
> + cf->can_id |= CAN_ERR_PROT;
> + cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
> + ndev->stats.rx_over_errors++;
> + ndev->stats.rx_errors++;
> + rcar_can_writeb(priv, RCAR_CAN_EIFR, (u8)~EIFR_OLIF);
> + }
> +
> + netif_rx(skb);
> + stats->rx_packets++;
> + stats->rx_bytes += cf->can_dlc;
> +}
> +
> +static irqreturn_t rcar_can_interrupt(int irq, void *dev_id)
> +{
> + struct net_device *ndev = (struct net_device *)dev_id;
> + struct rcar_can_priv *priv = netdev_priv(ndev);
> + struct net_device_stats *stats = &ndev->stats;
> + u8 isr;
> +
> + isr = rcar_can_readb(priv, RCAR_CAN_ISR);
> + if (isr & ISR_ERSF)
> + rcar_can_error(ndev);
> +
> + if (isr & ISR_TXMF) {
> + u32 ie_mask = 0;
> +
> + /* Set Transmit Mailbox Search Mode */
> + rcar_can_writeb(priv, RCAR_CAN_MSMR, MSMR_TXMB);
> + while (1) {
> + u8 mctl, mbx;
> +
> + mbx = rcar_can_readb(priv, RCAR_CAN_MSSR);
> + if (mbx & MSSR_SEST)
> + break;
> + mbx &= MSSR_MBNST;
> + mctl = rcar_can_readb(priv, RCAR_CAN_MCTL(mbx));
> + /* Bits SENTDATA and TRMREQ cannot be
> + * set to 0 simultaneously
> + */
> + mctl &= ~MCTL_TRMREQ;
> + rcar_can_writeb(priv, RCAR_CAN_MCTL(mbx), mctl);
> + mctl &= ~MCTL_SENTDATA;
> + /* Clear interrupt */
> + rcar_can_writeb(priv, RCAR_CAN_MCTL(mbx), mctl);
> + ie_mask |= BIT(mbx - FIRST_TX_MB);
> + stats->tx_bytes += can_get_echo_skb(ndev,
> + mbx - FIRST_TX_MB);
> + stats->tx_packets++;
> + can_led_event(ndev, CAN_LED_EVENT_TX);
> + }
> + /* Set receive mailbox search mode */
> + rcar_can_writeb(priv, RCAR_CAN_MSMR, MSMR_RXMB);
> + /* Disable mailbox interrupt, mark mailbox as free */
> + if (ie_mask) {
> + u32 mier1;
> +
> + spin_lock(&priv->mier_lock);
> + mier1 = rcar_can_readl(priv, RCAR_CAN_MIER1);
> + rcar_can_writel(priv, RCAR_CAN_MIER1, mier1 & ~ie_mask);
> + spin_unlock(&priv->mier_lock);
> + if (unlikely(netif_queue_stopped(ndev)))
> + netif_wake_queue(ndev);
> + }
> + }
> + if (isr & ISR_RXM1F) {
> + if (napi_schedule_prep(&priv->napi)) {
> + /* Disable Rx interrupts */
> + rcar_can_writeb(priv, RCAR_CAN_IER,
> + rcar_can_readb(priv, RCAR_CAN_IER) &
> + ~IER_RXM1IE);
> + __napi_schedule(&priv->napi);
> + }
> + }
> + return IRQ_HANDLED;
> +}
> +
> +static int rcar_can_set_bittiming(struct net_device *dev)
> +{
> + struct rcar_can_priv *priv = netdev_priv(dev);
> + struct can_bittiming *bt = &priv->can.bittiming;
> + u32 bcr;
> + u16 ctlr;
> + u8 clkr;
> +
> + ctlr = rcar_can_readw(priv, RCAR_CAN_CTLR);
> + if (ctlr & CTLR_SLPM) {
> + /* Write to BCR in CAN reset mode or CAN halt mode */
> + return -EBUSY;
> + }
> + /* Don't overwrite CLKR with 32-bit BCR access */
> + /* CLKR has 8-bit access */
> + clkr = rcar_can_readb(priv, RCAR_CAN_CLKR);
> + bcr = BCR_TSEG1(bt->phase_seg1 + bt->prop_seg - 1) |
> + BCR_BPR(bt->brp - 1) | BCR_SJW(bt->sjw - 1) |
> + BCR_TSEG2(bt->phase_seg2 - 1);
> + rcar_can_writel(priv, RCAR_CAN_BCR, bcr);
> + rcar_can_writeb(priv, RCAR_CAN_CLKR, clkr);
> + return 0;
> +}
> +
> +static void rcar_can_start(struct net_device *ndev)
> +{
> + struct rcar_can_priv *priv = netdev_priv(ndev);
> + u16 ctlr, n;
> +
> + /* Set controller to known mode:
> + * - normal mailbox mode (no FIFO);
> + * - accept all messages (no filter).
> + * CAN is in sleep mode after MCU hardware or software reset.
> + */
> + ctlr = rcar_can_readw(priv, RCAR_CAN_CTLR);
> + ctlr &= ~CTLR_SLPM;
> + rcar_can_writew(priv, RCAR_CAN_CTLR, ctlr);
> + /* Go to reset mode */
> + ctlr |= CTLR_FORCE_RESET;
> + rcar_can_writew(priv, RCAR_CAN_CTLR, ctlr);
> + ctlr |= CTLR_IDFM_MIXED; /* Select mixed ID mode */
> + ctlr &= ~CTLR_TPM; /* Set ID priority transmit mode */
> + rcar_can_writew(priv, RCAR_CAN_CTLR, ctlr);
> +
> + rcar_can_writeb(priv, RCAR_CAN_CLKR, priv->clock_select);
> +
> + /* Accept all SID and EID */
> + for (n = 0; n < N_RX_MKREGS; n++)
> + rcar_can_writel(priv, RCAR_CAN_MKR(n), 0);
> + rcar_can_writel(priv, RCAR_CAN_MKIVLR0, 0);
> +
> + rcar_can_set_bittiming(ndev);
> +
> + /* Initial value of MIER1 undefined. Mark all Tx mailboxes as free. */
> + rcar_can_writel(priv, RCAR_CAN_MIER1, 0);
> +
> + rcar_can_writeb(priv, RCAR_CAN_IER, IER_TXMIE | IER_ERSIE | IER_RXM1IE);
> +
> + /* Accumulate error codes */
> + rcar_can_writeb(priv, RCAR_CAN_ECSR, ECSR_EDPM);
> + /* Enable error interrupts */
> + rcar_can_writeb(priv, RCAR_CAN_EIER,
> + EIER_EWIE | EIER_EPIE | EIER_BOEIE | EIER_BEIE |
> + EIER_ORIE | EIER_OLIE);
> + /* Enable interrupts for RX mailboxes */
> + rcar_can_writel(priv, RCAR_CAN_MIER0, RX_MBX_MASK);
> + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +
> + /* Write to the CiMCTLj register in CAN
> + * operation mode or CAN halt mode.
> + * Configure mailboxes 0-31 as Rx mailboxes.
> + * Configure mailboxes 32-63 as Tx mailboxes.
> + */
> + /* Go to halt mode */
> + ctlr |= CTLR_HALT;
> + ctlr &= ~CTLR_RESET;
> + rcar_can_writew(priv, RCAR_CAN_CTLR, ctlr);
> + for (n = 0; n < FIRST_TX_MB; n++) {
> + /* According to documentation we should clear MCTL
> + * register before configuring mailbox.
> + */
> + rcar_can_writeb(priv, RCAR_CAN_MCTL(n), 0);
> + rcar_can_writeb(priv, RCAR_CAN_MCTL(n), MCTL_RECREQ);
> + rcar_can_writeb(priv, RCAR_CAN_MCTL(FIRST_TX_MB + n), 0);
> + }
> + /* Go to operation mode */
> + rcar_can_writew(priv, RCAR_CAN_CTLR, ctlr & ~CTLR_FORCE_RESET);
> +}
> +
> +static int rcar_can_open(struct net_device *ndev)
> +{
> + struct rcar_can_priv *priv = netdev_priv(ndev);
> + int err;
> +
> + err = open_candev(ndev);
> + if (err) {
> + netdev_err(ndev, "open_candev() failed %d\n", err);
> + goto out;
> + }
> + napi_enable(&priv->napi);
> + err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev);
> + if (err) {
> + netdev_err(ndev, "error requesting interrupt %x\n", ndev->irq);
> + goto out_close;
> + }
> + can_led_event(ndev, CAN_LED_EVENT_OPEN);
> + rcar_can_start(ndev);
> + netif_start_queue(ndev);
> + return 0;
> +out_close:
> + napi_disable(&priv->napi);
> + close_candev(ndev);
> +out:
> + return err;
> +}
> +
> +static void rcar_can_stop(struct net_device *ndev)
> +{
> + struct rcar_can_priv *priv = netdev_priv(ndev);
> + u16 ctlr;
> +
> + /* Go to (force) reset mode */
> + ctlr = rcar_can_readw(priv, RCAR_CAN_CTLR);
> + rcar_can_writew(priv, RCAR_CAN_CTLR, ctlr | CTLR_FORCE_RESET);
> + rcar_can_writel(priv, RCAR_CAN_MIER0, 0);
> + rcar_can_writel(priv, RCAR_CAN_MIER1, 0);
> + rcar_can_writeb(priv, RCAR_CAN_IER, 0);
> + rcar_can_writeb(priv, RCAR_CAN_EIER, 0);
> + priv->can.state = CAN_STATE_STOPPED;
> +}
> +
> +static int rcar_can_close(struct net_device *ndev)
> +{
> + struct rcar_can_priv *priv = netdev_priv(ndev);
> +
> + netif_stop_queue(ndev);
> + rcar_can_stop(ndev);
> + free_irq(ndev->irq, ndev);
> + napi_disable(&priv->napi);
> + close_candev(ndev);
> + can_led_event(ndev, CAN_LED_EVENT_STOP);
> + return 0;
> +}
> +
> +static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb,
> + struct net_device *ndev)
> +{
> + struct rcar_can_priv *priv = netdev_priv(ndev);
> + struct can_frame *cf = (struct can_frame *)skb->data;
> + u32 data, mier1, mbxno, i;
> + unsigned long flags;
> + u8 mctl;
> +
> + if (can_dropped_invalid_skb(ndev, skb))
> + return NETDEV_TX_OK;
> +
> + spin_lock_irqsave(&priv->mier_lock, flags);
> + mier1 = rcar_can_readl(priv, RCAR_CAN_MIER1);
> + if (unlikely(mier1 == ~0U)) {
> + spin_unlock_irqrestore(&priv->mier_lock, flags);
> + netif_stop_queue(ndev);
> + return NETDEV_TX_BUSY;
> + }
> + rcar_can_writel(priv, RCAR_CAN_MIER1, mier1 | (mier1 + 1));
> + spin_unlock_irqrestore(&priv->mier_lock, flags);
> + mbxno = ffz(mier1) + FIRST_TX_MB;
> +
> + if (cf->can_id & CAN_EFF_FLAG) {
> + /* Extended frame format */
> + data = (cf->can_id & CAN_EFF_MASK) | RCAR_CAN_IDE;
> + } else {
> + /* Standard frame format */
> + data = (cf->can_id & CAN_SFF_MASK) << RCAR_CAN_SID_SHIFT;
> + }
> + if (cf->can_id & CAN_RTR_FLAG) {
> + /* Remote transmission request */
> + data |= RCAR_CAN_RTR;
> + }
> + rcar_can_mbx_writel(priv, mbxno, MBX_HDR_OFFSET, data);
> +
> + rcar_can_mbx_writeb(priv, mbxno, MBX_DLC_OFFSET, cf->can_dlc);
> +
> + for (i = 0; i < cf->can_dlc; i++)
> + rcar_can_mbx_writeb(priv, mbxno,
> + MBX_DATA_OFFSET + i, cf->data[i]);
> +
> + can_put_echo_skb(skb, ndev, mbxno - FIRST_TX_MB);
> +
> + rcar_can_writeb(priv, RCAR_CAN_IER,
> + rcar_can_readb(priv, RCAR_CAN_IER) | IER_TXMIE);
> +
> + mctl = rcar_can_readb(priv, RCAR_CAN_MCTL(mbxno));
> + if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
> + mctl |= MCTL_ONESHOT;
> + else
> + mctl &= ~MCTL_ONESHOT;
> + /* Start TX */
> + mctl |= MCTL_TRMREQ;
> + rcar_can_writeb(priv, RCAR_CAN_MCTL(mbxno), mctl);
> + return NETDEV_TX_OK;
> +}
> +
> +static const struct net_device_ops rcar_can_netdev_ops = {
> + .ndo_open = rcar_can_open,
> + .ndo_stop = rcar_can_close,
> + .ndo_start_xmit = rcar_can_start_xmit,
> +};
> +
> +static void rcar_can_rx_pkt(struct rcar_can_priv *priv, int mbx)
> +{
> + struct net_device_stats *stats = &priv->ndev->stats;
> + struct can_frame *cf;
> + struct sk_buff *skb;
> + u32 data;
> + u8 dlc;
> +
> + skb = alloc_can_skb(priv->ndev, &cf);
> + if (!skb) {
> + stats->rx_dropped++;
> + if (printk_ratelimit())
> + netdev_err(priv->ndev,
> + "%s: alloc_can_skb() failed\n", __func__);
> + return;
> + }
> +
> + data = rcar_can_mbx_readl(priv, mbx, MBX_HDR_OFFSET);
> + if (data & RCAR_CAN_IDE)
> + cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG;
> + else
> + cf->can_id = (data >> RCAR_CAN_SID_SHIFT) & CAN_SFF_MASK;
> + if (data & RCAR_CAN_RTR)
> + cf->can_id |= CAN_RTR_FLAG;
> +
> + dlc = rcar_can_mbx_readb(priv, mbx, MBX_DLC_OFFSET);
> + cf->can_dlc = get_can_dlc(dlc);
> + for (dlc = 0; dlc < cf->can_dlc; dlc++)
> + cf->data[dlc] = rcar_can_mbx_readb(priv, mbx,
> + MBX_DATA_OFFSET + dlc);
> +
> + can_led_event(priv->ndev, CAN_LED_EVENT_RX);
> +
> + netif_receive_skb(skb);
> + stats->rx_bytes += cf->can_dlc;
> + stats->rx_packets++;
> +}
> +
> +static int rcar_can_rx_poll(struct napi_struct *napi, int quota)
> +{
> + struct rcar_can_priv *priv = container_of(napi,
> + struct rcar_can_priv, napi);
> + u32 num_pkts = 0;
> +
> + /* Find mailbox */
> + while (1) {
> + u8 mctl, mbx;
> +
> + mbx = rcar_can_readb(priv, RCAR_CAN_MSSR);
> + if (mbx & MSSR_SEST || num_pkts >= quota)
> + break;
> + mbx &= MSSR_MBNST;
> + mctl = rcar_can_readb(priv, RCAR_CAN_MCTL(mbx));
> + /* Clear interrupt */
> + rcar_can_writeb(priv, RCAR_CAN_MCTL(mbx),
> + mctl & ~MCTL_NEWDATA);
> + rcar_can_rx_pkt(priv, mbx);
> + ++num_pkts;
> + }
> + /* All packets processed */
> + if (num_pkts < quota) {
> + u8 ier;
> +
> + napi_complete(napi);
> + ier = rcar_can_readb(priv, RCAR_CAN_IER);
> + rcar_can_writeb(priv, RCAR_CAN_IER, ier | IER_RXM1IE);
> + }
> + return num_pkts;
> +}
> +
> +static int rcar_can_do_set_mode(struct net_device *ndev, enum can_mode mode)
> +{
> + switch (mode) {
> + case CAN_MODE_START:
> + rcar_can_start(ndev);
> + netif_wake_queue(ndev);
> + return 0;
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static int rcar_can_get_berr_counter(const struct net_device *dev,
> + struct can_berr_counter *bec)
> +{
> + struct rcar_can_priv *priv = netdev_priv(dev);
> +
> + bec->txerr = rcar_can_readb(priv, RCAR_CAN_TECR);
> + bec->rxerr = rcar_can_readb(priv, RCAR_CAN_RECR);
> + return 0;
> +}
> +
> +static int rcar_can_probe(struct platform_device *pdev)
> +{
> + struct rcar_can_platform_data *pdata;
> + struct rcar_can_priv *priv;
> + struct net_device *ndev;
> + struct resource *mem;
> + void __iomem *addr;
> + int err = -ENODEV;
> + int irq;
> +
> + pdata = pdev->dev.platform_data;
> + if (!pdata) {
> + dev_err(&pdev->dev, "No platform data provided!\n");
> + goto fail;
> + }
> +
> + irq = platform_get_irq(pdev, 0);
> + if (!irq) {
> + dev_err(&pdev->dev, "No IRQ resource\n");
> + goto fail;
> + }
> +
> + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + addr = devm_ioremap_resource(&pdev->dev, mem);
> + if (IS_ERR(addr)) {
> + err = PTR_ERR(addr);
> + goto fail;
> + }
> +
> + ndev = alloc_candev(sizeof(struct rcar_can_priv), N_MBX - FIRST_TX_MB);
> + if (!ndev) {
> + dev_err(&pdev->dev, "alloc_candev failed\n");
> + err = -ENOMEM;
> + goto fail;
> + }
> +
> + priv = netdev_priv(ndev);
> +
> + priv->clk = devm_clk_get(&pdev->dev, NULL);
> + if (IS_ERR(priv->clk)) {
> + err = PTR_ERR(priv->clk);
> + dev_err(&pdev->dev, "cannot get clock: %d\n", err);
> + goto fail_clk;
> + }
> + clk_enable(priv->clk);
> +
> + ndev->netdev_ops = &rcar_can_netdev_ops;
> + ndev->irq = irq;
> + ndev->flags |= IFF_ECHO;
> + priv->ndev = ndev;
> + priv->reg_base = addr;
> + priv->clock_select = pdata->clock_select;
> + priv->can.clock.freq = clk_get_rate(priv->clk);
> + priv->can.bittiming_const = &rcar_can_bittiming_const;
> + priv->can.do_set_bittiming = rcar_can_set_bittiming;
> + priv->can.do_set_mode = rcar_can_do_set_mode;
> + priv->can.do_get_berr_counter = rcar_can_get_berr_counter;
> + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
> + CAN_CTRLMODE_ONE_SHOT;
> + platform_set_drvdata(pdev, ndev);
> + SET_NETDEV_DEV(ndev, &pdev->dev);
> + spin_lock_init(&priv->mier_lock);
> +
> + netif_napi_add(ndev, &priv->napi, rcar_can_rx_poll,
> + RCAR_CAN_NAPI_WEIGHT);
> + err = register_candev(ndev);
> + if (err) {
> + dev_err(&pdev->dev, "register_candev() failed\n");
> + goto fail_candev;
> + }
> +
> + devm_can_led_init(ndev);
> +
> + dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n",
> + priv->reg_base, ndev->irq);
> +
> + return 0;
> +fail_candev:
> + netif_napi_del(&priv->napi);
> +fail_clk:
> + free_candev(ndev);
> +fail:
> + return err;
> +}
> +
> +static int rcar_can_remove(struct platform_device *pdev)
> +{
> + struct net_device *ndev = platform_get_drvdata(pdev);
> + struct rcar_can_priv *priv = netdev_priv(ndev);
> + u16 ctlr;
> +
> + unregister_candev(ndev);
> + netif_napi_del(&priv->napi);
> + /* Go to sleep mode */
> + ctlr = rcar_can_readw(priv, RCAR_CAN_CTLR);
> + rcar_can_writew(priv, RCAR_CAN_CTLR, ctlr | CTLR_SLPM);
> + clk_disable(priv->clk);
> + free_candev(ndev);
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int rcar_can_suspend(struct device *dev)
> +{
> + struct net_device *ndev = dev_get_drvdata(dev);
> + struct rcar_can_priv *priv = netdev_priv(ndev);
> + u16 ctlr;
> +
> + if (netif_running(ndev)) {
> + netif_stop_queue(ndev);
> + netif_device_detach(ndev);
> + }
> + ctlr = rcar_can_readw(priv, RCAR_CAN_CTLR);
> + ctlr |= CTLR_HALT;
> + rcar_can_writew(priv, RCAR_CAN_CTLR, ctlr);
> + ctlr |= CTLR_SLPM;
> + rcar_can_writew(priv, RCAR_CAN_CTLR, ctlr);
> + priv->can.state = CAN_STATE_SLEEPING;
> +
> + clk_disable(priv->clk);
> + return 0;
> +}
> +
> +static int rcar_can_resume(struct device *dev)
> +{
> + struct net_device *ndev = dev_get_drvdata(dev);
> + struct rcar_can_priv *priv = netdev_priv(ndev);
> + u16 ctlr;
> +
> + clk_enable(priv->clk);
> +
> + ctlr = rcar_can_readw(priv, RCAR_CAN_CTLR);
> + ctlr &= ~CTLR_SLPM;
> + rcar_can_writew(priv, RCAR_CAN_CTLR, ctlr);
> + ctlr &= ~CTLR_FORCE_RESET;
> + rcar_can_writew(priv, RCAR_CAN_CTLR, ctlr);
> + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +
> + if (netif_running(ndev)) {
> + netif_device_attach(ndev);
> + netif_start_queue(ndev);
> + }
> + return 0;
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(rcar_can_pm_ops, rcar_can_suspend, rcar_can_resume);
> +
> +static struct platform_driver rcar_can_driver = {
> + .driver = {
> + .name = DRV_NAME,
> + .owner = THIS_MODULE,
> + .pm = &rcar_can_pm_ops,
> + },
> + .probe = rcar_can_probe,
> + .remove = rcar_can_remove,
> +};
> +
> +module_platform_driver(rcar_can_driver);
> +
> +MODULE_AUTHOR("Cogent Embedded, Inc.");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("CAN driver for Renesas R-Car SoC");
> +MODULE_ALIAS("platform:" DRV_NAME);
> Index: linux-can-next/include/linux/can/platform/rcar_can.h
> ===================================================================
> --- /dev/null
> +++ linux-can-next/include/linux/can/platform/rcar_can.h
> @@ -0,0 +1,15 @@
> +#ifndef _CAN_PLATFORM_RCAR_CAN_H_
> +#define _CAN_PLATFORM_RCAR_CAN_H_
> +
> +#include <linux/types.h>
> +
> +/* Clock Select Register settings */
> +#define CLKR_CLKEXT 3 /* Externally input clock */
> +#define CLKR_CLKP2 1 /* Peripheral clock (clkp2) */
> +#define CLKR_CLKP1 0 /* Peripheral clock (clkp1) */
> +
> +struct rcar_can_platform_data {
> + u8 clock_select; /* Clock source select */
> +};
> +
> +#endif /* !_CAN_PLATFORM_RCAR_CAN_H_ */
> --
> To unsubscribe from this list: send the line "unsubscribe linux-can" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
^ permalink raw reply
* [PATCH] netif_set_xps_queue: make cpu mask const
From: Michael S. Tsirkin @ 2013-10-02 6:14 UTC (permalink / raw)
To: Jason Wang, rusty
Cc: David S. Miller, Eric Dumazet, Jiri Pirko, Vlad Yasevich,
Cong Wang, Alexander Duyck, netdev, linux-kernel
virtio wants to pass in cpumask_of(cpu), make parameter
const to avoid build warnings.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/netdevice.h | 5 +++--
net/core/dev.c | 3 ++-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3de49ac..25f5d2d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2264,11 +2264,12 @@ static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
}
#ifdef CONFIG_XPS
-extern int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask,
+extern int netif_set_xps_queue(struct net_device *dev,
+ const struct cpumask *mask,
u16 index);
#else
static inline int netif_set_xps_queue(struct net_device *dev,
- struct cpumask *mask,
+ const struct cpumask *mask,
u16 index)
{
return 0;
diff --git a/net/core/dev.c b/net/core/dev.c
index 5c713f2..f18eebd 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1917,7 +1917,8 @@ static struct xps_map *expand_xps_map(struct xps_map *map,
return new_map;
}
-int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask, u16 index)
+int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
+ u16 index)
{
struct xps_dev_maps *dev_maps, *new_dev_maps = NULL;
struct xps_map *map, *new_map;
--
MST
^ permalink raw reply related
* Re: [net-next PATCH V2] virtio-net: switch to use XPS to choose txq
From: Michael S. Tsirkin @ 2013-10-02 6:15 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-kernel, virtualization
In-Reply-To: <20130930.221040.543720988967287293.davem@davemloft.net>
On Mon, Sep 30, 2013 at 10:10:40PM -0700, David Miller wrote:
> From: Jason Wang <jasowang@redhat.com>
> Date: Mon, 30 Sep 2013 15:37:17 +0800
>
> > We used to use a percpu structure vq_index to record the cpu to queue
> > mapping, this is suboptimal since it duplicates the work of XPS and
> > loses all other XPS functionality such as allowing use to configure
> > their own transmission steering strategy.
> >
> > So this patch switches to use XPS and suggest a default mapping when
> > the number of cpus is equal to the number of queues. With XPS support,
> > there's no need for keeping per-cpu vq_index and .ndo_select_queue(),
> > so they were removed also.
> >
> > Cc: Rusty Russell <rusty@rustcorp.com.au>
> > Cc: Michael S. Tsirkin <mst@redhat.com>
> > Signed-off-by: Jason Wang <jasowang@redhat.com>
> > ---
> > Changes from V1:
> > - use cpumask_of() instead of allocate dynamically
>
> This generates build warnings:
>
> drivers/net/virtio_net.c: In function ‘virtnet_set_affinity’:
> drivers/net/virtio_net.c:1093:3: warning: passing argument 2 of ‘netif_set_xps_queue’ discards ‘const’ qualifier from pointer target type [enabled by default]
> In file included from drivers/net/virtio_net.c:20:0:
> include/linux/netdevice.h:2275:5: note: expected ‘struct cpumask *’ but argument is of type ‘const struct cpumask *’
Looks like we just need to tweak the signature there to const struct
cpumask *: it's never changed.
I just sent a patch
[PATCH] netif_set_xps_queue: make cpu mask const
that does exactly that.
--
MST
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [RFC PATCH 0/2] net: alternate proposal for using macvlans with forwarding acceleration
From: John Fastabend @ 2013-10-02 6:31 UTC (permalink / raw)
To: Neil Horman; +Cc: netdev
In-Reply-To: <1380140209-24587-1-git-send-email-nhorman@tuxdriver.com>
On 09/25/2013 01:16 PM, Neil Horman wrote:
> John, et al. -
> As promised, heres my (very rough) first pass at an alternate propsal for
> what you're trying to do with virtual station interfaces here. Its completely
> untested, but it builds, and I'll be trying to run it over the next few days
> (though I'm sure I got part of the hardware manipulation wrong). I wanted to
> post it early though so you could get a look at it to see what you did and
> didn't like about it. Some notes:
Sorry for the delay. I like the idea one nice win here is my macvlan
kvm setup would use the offloads without having to reconfigure.
>
> 1) As discussed, the major effort here is to tie in macvlans with l2 forwarding
> acceleration, rather than creating a new vsi link type. That should make
> management easier for admins (be it via ovs or some other mechanism). It
> basically exposes a bit less to the user, which I think is good.
>
The trick here is the offload path may be functionally different from
the non-offload path. The user needs some visibility into this. For
example any qdiscs running on the lowerdev will not be visible from the
accelerated path.
When a new link type was being used I was able to convince myself that
it was a property of the link type. But if we reuse macvlan I think we
need some way to either automatically disable the offload path when this
occurs or provide the user visibility. Maybe a feature flag and a
netif_can_hw_offload() routine is needed?
> 2) I've separated out the l2 forwarding acceleration operations from the
> net_device_operations structure. I'm not sure I like that yet, but I'm kind on
> leaning that way. Since a limited set of hardare supports forwarding
> acceleration, it makes for a nice easy way to group functionality without
> polluting the net_device_operations structure. It also lets us group simmilar
> functions together nicely (I can see a future l3_accel_ops structure if we can
> do l3 flows in hardware). Anywho, its a divergence from what we've been doing
> so I thought I would call attention to it.
>
> 3) I've included a l2_accel_xmit method in the accel_ops structure for fast path
> forwarding, but I'm not sure I like that. It seems we should be able to use
> ndo_start_xmit and key off some data to recognize that we should be doing
> hardware forwarding. I'm not quite sure how to do that yet though. Something
> to think about.
Without a specific xmit routine though you will be adding operations in
the common case for a special case. Having a new op fixes this.
>
> 4) I've borrowed heavily from your vsi work of course just to get this building.
> I think theres probbaly alot of consolidation that can be done in the code that
> I added to ixgbe_main.c to make it smaller. Again, I just wanted to post this
> so you could speak up if you though this was all crap before I wen't too far
> down the rabbit hole.
There was some consolidation needed in my original RFC as well. I can
help clean some of this stuff up if you want.
.John
--
John Fastabend Intel Corporation
^ permalink raw reply
* Re: [PATCH net-next] net:drivers/net: Miscellaneous conversions to ETH_ALEN
From: Joe Perches @ 2013-10-02 6:40 UTC (permalink / raw)
To: Kalle Valo, netdev; +Cc: ath10k
In-Reply-To: <87k3hw469z.fsf@kamboji.qca.qualcomm.com>
On Wed, 2013-10-02 at 07:59 +0300, Kalle Valo wrote:
> (Cutting the CC smaller)
Please include netdev. (cc'd)
> Joe Perches <joe@perches.com> writes:
>
> > Convert the memset/memcpy uses of 6 to ETH_ALEN
> > where appropriate.
[]
> > Signed-off-by: Joe Perches <joe@perches.com>
[]
> Acked-by: Kalle Valo <kvalo@qca.qualcomm.com>
^ permalink raw reply
* [PATCH 1/1] hso: fix problem with wrong status code sent by OPTION GTM601 during RING indication
From: Dr. H. Nikolaus Schaller @ 2013-10-02 7:00 UTC (permalink / raw)
To: Jan Dumon; +Cc: Belisko Marek, linux-usb, netdev, linux-kernel
Hi Jan,
we are using a GTM601 modem (Firmware 1.7) for a while and have spotted an
issue that under some conditions the modem sends a packed wIndex over USB
that is rejected by the hso driver making troubles afterwards. Not rejecting makes
it work fine.
BR,
Nikolaus Schaller
---
>From f5c7e15b61f2ce4fe3105ff914f6bfaf5d74af0d Mon Sep 17 00:00:00 2001
From: "H. Nikolaus Schaller" <hns@goldelico.com>
Date: Thu, 15 Nov 2012 14:40:57 +0100
Subject: [PATCH 1/1] hso: fix problem with wrong status code sent by OPTION
GTM601 during RING indication
It has been observed that the GTM601 with 1.7 firmware sometimes sends a value
wIndex that has bit 0x04 set instead of being reset as the code expects. So we
mask it for the error check.
See http://lists.goldelico.com/pipermail/gta04-owner/2012-February/001643.html
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.de>
---
drivers/net/usb/hso.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index cba1d46..d146e26 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1503,7 +1503,8 @@ static void tiocmget_intr_callback(struct urb *urb)
if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE ||
serial_state_notification->bNotification != B_NOTIFICATION ||
le16_to_cpu(serial_state_notification->wValue) != W_VALUE ||
- le16_to_cpu(serial_state_notification->wIndex) != W_INDEX ||
+ (le16_to_cpu(serial_state_notification->wIndex) & ~0x4) !=
+ W_INDEX ||
le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) {
dev_warn(&usb->dev,
"hso received invalid serial state notification\n");
--
1.7.7.4
^ permalink raw reply related
* Re: [RFC PATCH 1/2] net: Add layer 2 hardware acceleration operations for macvlan devices
From: John Fastabend @ 2013-10-02 7:08 UTC (permalink / raw)
To: Neil Horman; +Cc: netdev, john.fastabend, David S. Miller
In-Reply-To: <1380140209-24587-2-git-send-email-nhorman@tuxdriver.com>
On 09/25/2013 01:16 PM, Neil Horman wrote:
> Add a operations structure that allows a network interface to export the fact
> that it supports package forwarding in hardware between physical interfaces and
> other mac layer devices assigned to it (such as macvlans). this operaions
> structure can be used by virtual mac devices to bypass software switching so
> that forwarding can be done in hardware more efficiently.
Some additional nits below which maybe you have already thought of.
>
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> CC: john.fastabend@intel.com
> CC: "David S. Miller" <davem@davemloft.net>
> ---
> drivers/net/macvlan.c | 37 +++++++++++++++++++++++++++++++++++++
> include/linux/if_macvlan.h | 1 +
> include/linux/netdevice.h | 10 ++++++++++
> net/core/dev.c | 3 +++
> 4 files changed, 51 insertions(+)
>
> diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
> index 9bf46bd..0c37b30 100644
> --- a/drivers/net/macvlan.c
> +++ b/drivers/net/macvlan.c
> @@ -296,8 +296,16 @@ netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
> unsigned int len = skb->len;
> int ret;
> const struct macvlan_dev *vlan = netdev_priv(dev);
> + const struct l2_forwarding_accel_ops *l2a_ops = vlan->lowerdev->l2a_ops;
> +
> + if (l2a_ops->l2_accel_xmit) {
> + ret = l2a_ops->l2_accel_xmit(skb, vlan->l2a_priv);
> + if (likely(ret == NETDEV_TX_OK))
maybe dev_xmit_complete() would be more appropriate?
> + goto update_stats;
> + }
>
> ret = macvlan_queue_xmit(skb, dev);
> +update_stats:
> if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
> struct macvlan_pcpu_stats *pcpu_stats;
>
> @@ -336,6 +344,7 @@ static int macvlan_open(struct net_device *dev)
> {
> struct macvlan_dev *vlan = netdev_priv(dev);
> struct net_device *lowerdev = vlan->lowerdev;
> + const struct l2_forwarding_accel_ops *l2a_ops = lowerdev->l2a_ops;
> int err;
>
> if (vlan->port->passthru) {
> @@ -347,6 +356,19 @@ static int macvlan_open(struct net_device *dev)
> goto hash_add;
Looks like this might break in the passthru case? If you don't call
l2_accel_add_dev here but still use the l2_accel_xmit.
> }
>
> + if (l2a_ops->l2_accel_add_dev) {
In the error cases it might be preferred to fallback to the
non-offloaded software path. For example hardware may have a limit
to the number of VSIs that can be created but we wouldn't want to
push that up the stack.
> + /* The lowerdev supports l2 switching
> + * try to add this macvlan to it
> + */
> + vlan->l2a_priv = kzalloc(l2a_ops->priv_size, GFP_KERNEL);
> + if (!vlan->l2a_priv)
> + return -ENOMEM;
> + err = l2a_ops->l2_accel_add_dev(vlan->lowerdev,
> + dev, vlan->l2a_priv);
> + if (err < 0)
> + return err;
> + }
> +
> err = -EBUSY;
> if (macvlan_addr_busy(vlan->port, dev->dev_addr))
> goto out;
> @@ -367,6 +389,13 @@ hash_add:
> del_unicast:
> dev_uc_del(lowerdev, dev->dev_addr);
> out:
> + if (vlan->l2a_priv) {
Add a feature flag here so it can be disabled.
> + if (l2a_ops->l2_accel_del_dev)
> + l2a_ops->l2_accel_del_dev(vlan->lowerdev,
> + vlan->l2a_priv);
> + kfree(vlan->l2a_priv);
> + vlan->l2a_priv = NULL;
> + }
> return err;
> }
[...]
Thanks,
John
--
John Fastabend Intel Corporation
^ permalink raw reply
* Re: [PATCH net 1/2] sit: allow to use rtnl ops on fb tunnel
From: Nicolas Dichtel @ 2013-10-02 7:15 UTC (permalink / raw)
To: David Miller; +Cc: netdev, steffen.klassert, pshelar
In-Reply-To: <20131001.125923.700243113980583930.davem@davemloft.net>
Le 01/10/2013 18:59, David Miller a écrit :
> From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> Date: Tue, 1 Oct 2013 18:04:59 +0200
>
>> rtnl ops where introduced by ba3e3f50a0e5 ("sit: advertise tunnel param via
>> rtnl"), but I forget to assign rtnl ops to fb tunnels.
>>
>> Now that it is done, we must remove the explicit call to
>> unregister_netdevice_queue(), because the fallback tunnel is added to the queue
>> in sit_destroy_tunnels() when checking rtnl_link_ops of all netdevices (this
>> is valid since commit 5e6700b3bf98 ("sit: add support of x-netns")).
>>
>> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>
> Applied and queued up for -stable.
>
> But I imagine since the x-netns changes aren't in various -stable
> branches this will need to be adjusted a bit?
Yes, it's what I've tried to say in the commit log ;-)
In fact, before the x-netns changes, we must keep the
unregister_netdevice_queue() line.
^ permalink raw reply
* Re: [PATCH net 2/2] ip6tnl: allow to use rtnl ops on fb tunnel
From: Nicolas Dichtel @ 2013-10-02 7:16 UTC (permalink / raw)
To: David Miller; +Cc: netdev, steffen.klassert, pshelar
In-Reply-To: <20131001.125942.775476054819333568.davem@davemloft.net>
Le 01/10/2013 18:59, David Miller a écrit :
> From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> Date: Tue, 1 Oct 2013 18:05:00 +0200
>
>> rtnl ops where introduced by c075b13098b3 ("ip6tnl: advertise tunnel param via
>> rtnl"), but I forget to assign rtnl ops to fb tunnels.
>>
>> Now that it is done, we must remove the explicit call to
>> unregister_netdevice_queue(), because the fallback tunnel is added to the queue
>> in ip6_tnl_destroy_tunnels() when checking rtnl_link_ops of all netdevices (this
>> is valid since commit 0bd8762824e7 ("ip6tnl: add x-netns support")).
>>
>> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>
> Applied and queued up for -stable, and I have similar concerns about
> the backport issues.
>
> Thanks.
>
Yes, same here: before the x-netns changes, we must keep the
unregister_netdevice_queue() line.
^ permalink raw reply
* Re: [PATCH net-next] net:drivers/net: Miscellaneous conversions to ETH_ALEN
From: Arend van Spriel @ 2013-10-02 7:27 UTC (permalink / raw)
To: Joe Perches, netdev
Cc: linux-kernel, linuxppc-dev, e1000-devel, linux-usb, ath10k,
linux-wireless, wil6210, b43-dev, brcm80211-dev-list, bridge,
netfilter-devel
In-Reply-To: <1380679480.2081.24.camel@joe-AO722>
On 10/02/2013 04:04 AM, Joe Perches wrote:
> Convert the memset/memcpy uses of 6 to ETH_ALEN
> where appropriate.
>
> Also convert some struct definitions and u8 array
> declarations of [6] to ETH_ALEN.
>
For brcmsmac
Acked-by: Arend van Spriel <arend@broadcom.com>
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
> drivers/net/wireless/brcm80211/brcmsmac/main.c | 6 +-
^ permalink raw reply
* Re: [PATCH net 1/2] sit: allow to use rtnl ops on fb tunnel
From: Nicolas Dichtel @ 2013-10-02 7:36 UTC (permalink / raw)
To: David Miller; +Cc: netdev, steffen.klassert, pshelar
In-Reply-To: <524BC816.1000702@6wind.com>
Le 02/10/2013 09:15, Nicolas Dichtel a écrit :
> Le 01/10/2013 18:59, David Miller a écrit :
>> From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>> Date: Tue, 1 Oct 2013 18:04:59 +0200
>>
>>> rtnl ops where introduced by ba3e3f50a0e5 ("sit: advertise tunnel param via
>>> rtnl"), but I forget to assign rtnl ops to fb tunnels.
>>>
>>> Now that it is done, we must remove the explicit call to
>>> unregister_netdevice_queue(), because the fallback tunnel is added to the queue
>>> in sit_destroy_tunnels() when checking rtnl_link_ops of all netdevices (this
>>> is valid since commit 5e6700b3bf98 ("sit: add support of x-netns")).
>>>
>>> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>>
>> Applied and queued up for -stable.
Another things about ipip: between 0974658da47c ("ipip: advertise tunnel param
via rtnl", v3.8) and fd58156e456d ("IPIP: Use ip-tunneling code.", v3.10) the
fb device of ipip module has the same problem.
Should I send a patch?
^ permalink raw reply
* [PATCH v3] l2tp: fix kernel panic when using IPv4-mapped IPv6 addresses
From: François Cachereul @ 2013-10-02 8:16 UTC (permalink / raw)
To: David S. Miller, James Chapman; +Cc: netdev
IPv4 mapped addresses cause kernel panic.
The patch juste check whether the IPv6 address is an IPv4 mapped
address. If so, use IPv4 API instead of IPv6.
[ 940.026915] general protection fault: 0000 [#1]
[ 940.026915] Modules linked in: l2tp_ppp l2tp_netlink l2tp_core pppox ppp_generic slhc loop psmouse
[ 940.026915] CPU: 0 PID: 3184 Comm: memcheck-amd64- Not tainted 3.11.0+ #1
[ 940.026915] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007
[ 940.026915] task: ffff880007130e20 ti: ffff88000737e000 task.ti: ffff88000737e000
[ 940.026915] RIP: 0010:[<ffffffff81333780>] [<ffffffff81333780>] ip6_xmit+0x276/0x326
[ 940.026915] RSP: 0018:ffff88000737fd28 EFLAGS: 00010286
[ 940.026915] RAX: c748521a75ceff48 RBX: ffff880000c30800 RCX: 0000000000000000
[ 940.026915] RDX: ffff88000075cc4e RSI: 0000000000000028 RDI: ffff8800060e5a40
[ 940.026915] RBP: ffff8800060e5a40 R08: 0000000000000000 R09: ffff88000075cc90
[ 940.026915] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88000737fda0
[ 940.026915] R13: 0000000000000000 R14: 0000000000002000 R15: ffff880005d3b580
[ 940.026915] FS: 00007f163dc5e800(0000) GS:ffffffff81623000(0000) knlGS:0000000000000000
[ 940.026915] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 940.026915] CR2: 00000004032dc940 CR3: 0000000005c25000 CR4: 00000000000006f0
[ 940.026915] Stack:
[ 940.026915] ffff88000075cc4e ffffffff81694e90 ffff880000c30b38 0000000000000020
[ 940.026915] 11000000523c4bac ffff88000737fdb4 0000000000000000 ffff880000c30800
[ 940.026915] ffff880005d3b580 ffff880000c30b38 ffff8800060e5a40 0000000000000020
[ 940.026915] Call Trace:
[ 940.026915] [<ffffffff81356cc3>] ? inet6_csk_xmit+0xa4/0xc4
[ 940.026915] [<ffffffffa0038535>] ? l2tp_xmit_skb+0x503/0x55a [l2tp_core]
[ 940.026915] [<ffffffff812b8d3b>] ? pskb_expand_head+0x161/0x214
[ 940.026915] [<ffffffffa003e91d>] ? pppol2tp_xmit+0xf2/0x143 [l2tp_ppp]
[ 940.026915] [<ffffffffa00292e0>] ? ppp_channel_push+0x36/0x8b [ppp_generic]
[ 940.026915] [<ffffffffa00293fe>] ? ppp_write+0xaf/0xc5 [ppp_generic]
[ 940.026915] [<ffffffff8110ead4>] ? vfs_write+0xa2/0x106
[ 940.026915] [<ffffffff8110edd6>] ? SyS_write+0x56/0x8a
[ 940.026915] [<ffffffff81378ac0>] ? system_call_fastpath+0x16/0x1b
[ 940.026915] Code: 00 49 8b 8f d8 00 00 00 66 83 7c 11 02 00 74 60 49
8b 47 58 48 83 e0 fe 48 8b 80 18 01 00 00 48 85 c0 74 13 48 8b 80 78 02
00 00 <48> ff 40 28 41 8b 57 68 48 01 50 30 48 8b 54 24 08 49 c7 c1 51
[ 940.026915] RIP [<ffffffff81333780>] ip6_xmit+0x276/0x326
[ 940.026915] RSP <ffff88000737fd28>
[ 940.057945] ---[ end trace be8aba9a61c8b7f3 ]---
[ 940.058583] Kernel panic - not syncing: Fatal exception in interrupt
Signed-off-by: François CACHEREUL <f.cachereul@alphalink.fr>
---
v3: add panic message
Sorry for the dumb oversight
net/l2tp/l2tp_core.c | 27 +++++++++++++++++++++++----
net/l2tp/l2tp_core.h | 3 +++
2 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index feae495..aedaa2c 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -496,6 +496,7 @@ out:
static inline int l2tp_verify_udp_checksum(struct sock *sk,
struct sk_buff *skb)
{
+ struct l2tp_tunnel *tunnel = (struct l2tp_tunnel *)sk->sk_user_data;
struct udphdr *uh = udp_hdr(skb);
u16 ulen = ntohs(uh->len);
__wsum psum;
@@ -504,7 +505,7 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk,
return 0;
#if IS_ENABLED(CONFIG_IPV6)
- if (sk->sk_family == PF_INET6) {
+ if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) {
if (!uh->check) {
LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n");
return 1;
@@ -1128,7 +1129,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
/* Queue the packet to IP for output */
skb->local_df = 1;
#if IS_ENABLED(CONFIG_IPV6)
- if (skb->sk->sk_family == PF_INET6)
+ if (skb->sk->sk_family == PF_INET6 && !tunnel->v4mapped)
error = inet6_csk_xmit(skb, NULL);
else
#endif
@@ -1255,7 +1256,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
/* Calculate UDP checksum if configured to do so */
#if IS_ENABLED(CONFIG_IPV6)
- if (sk->sk_family == PF_INET6)
+ if (sk->sk_family == PF_INET6 && !tunnel->v4mapped)
l2tp_xmit_ipv6_csum(sk, skb, udp_len);
else
#endif
@@ -1704,6 +1705,24 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
if (cfg != NULL)
tunnel->debug = cfg->debug;
+#if IS_ENABLED(CONFIG_IPV6)
+ if (sk->sk_family == PF_INET6) {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+
+ if (ipv6_addr_v4mapped(&np->saddr) &&
+ ipv6_addr_v4mapped(&np->daddr)) {
+ struct inet_sock *inet = inet_sk(sk);
+
+ tunnel->v4mapped = true;
+ inet->inet_saddr = np->saddr.s6_addr32[3];
+ inet->inet_rcv_saddr = np->rcv_saddr.s6_addr32[3];
+ inet->inet_daddr = np->daddr.s6_addr32[3];
+ } else {
+ tunnel->v4mapped = false;
+ }
+ }
+#endif
+
/* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
tunnel->encap = encap;
if (encap == L2TP_ENCAPTYPE_UDP) {
@@ -1712,7 +1731,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv;
udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy;
#if IS_ENABLED(CONFIG_IPV6)
- if (sk->sk_family == PF_INET6)
+ if (sk->sk_family == PF_INET6 && !tunnel->v4mapped)
udpv6_encap_enable();
else
#endif
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 66a559b..6f251cb 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -194,6 +194,9 @@ struct l2tp_tunnel {
struct sock *sock; /* Parent socket */
int fd; /* Parent fd, if tunnel socket
* was created by userspace */
+#if IS_ENABLED(CONFIG_IPV6)
+ bool v4mapped;
+#endif
struct work_struct del_work;
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH] ipv6: udp packets following an UFO enqueued packet need also be handled by UFO
From: Jiri Pirko @ 2013-10-02 8:58 UTC (permalink / raw)
To: netdev, yoshfuji, davem, kuznet, jmorris, kaber, herbert,
eric.dumazet
In-Reply-To: <20131001232534.GM10771@order.stressinduktion.org>
Wed, Oct 02, 2013 at 01:25:34AM CEST, hannes@stressinduktion.org wrote:
>On Tue, Oct 01, 2013 at 11:47:21PM +0200, Hannes Frederic Sowa wrote:
>> The strange thing is that if I don't do the IPV6_MTU setsockopt I don't
>> get an oops.
>
>This is incorrect, it just depends on the size of the writes and on the
>interface mtu.
>
>> IPv4 seems to work without problems, too.
>
>I also get kernel oopses from IPv4 now, too.
>
>
>So, skb_is_gso is not accurate enough in the output and we have to check if we
>already started to append to skb frags. The following diff does resolve this
>issue in both the IPv4 and IPv6 non-page-append output path but I am not
>confident if it is correct:
>
>diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
>index 6d56840..3565450 100644
>--- a/include/linux/skbuff.h
>+++ b/include/linux/skbuff.h
>@@ -1308,6 +1308,11 @@ static inline int skb_pagelen(const struct sk_buff *skb)
> return len + skb_headlen(skb);
> }
>
>+static inline bool skb_has_frags(const struct sk_buff *skb)
>+{
>+ return skb_shinfo(skb)->nr_frags;
>+}
>+
> /**
> * __skb_fill_page_desc - initialise a paged fragment in an skb
> * @skb: buffer containing fragment to be initialised
>diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
>index 7d8357b..8dc3d8d 100644
>--- a/net/ipv4/ip_output.c
>+++ b/net/ipv4/ip_output.c
>@@ -836,7 +836,7 @@ static int __ip_append_data(struct sock *sk,
> csummode = CHECKSUM_PARTIAL;
>
> cork->length += length;
>- if (((length > mtu) || (skb && skb_is_gso(skb))) &&
>+ if (((length > mtu) || (skb && skb_has_frags(skb))) &&
> (sk->sk_protocol == IPPROTO_UDP) &&
> (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) {
> err = ip_ufo_append_data(sk, queue, getfrag, from, length,
>diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
>index a54c45c..ded4f6f 100644
>--- a/net/ipv6/ip6_output.c
>+++ b/net/ipv6/ip6_output.c
>@@ -1227,7 +1227,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
> skb = skb_peek_tail(&sk->sk_write_queue);
> cork->length += length;
> if (((length > mtu) ||
>- (skb && skb_is_gso(skb))) &&
>+ (skb && skb_has_frags(skb))) &&
> (sk->sk_protocol == IPPROTO_UDP) &&
> (rt->dst.dev->features & NETIF_F_UFO)) {
> err = ip6_ufo_append_data(sk, getfrag, from, length,
>
>Greetings,
>
> Hannes
>
This seems correct to me. sk_is_gso would work as well is you apply my
patch "[patch net] ip6_output: do skb ufo init for peeked non ufo skb as
well" which does the setting of gso_size.
Jiri
^ permalink raw reply
* Re: [PATCH] ipv6: udp packets following an UFO enqueued packet need also be handled by UFO
From: Jiri Pirko @ 2013-10-02 10:33 UTC (permalink / raw)
To: netdev, yoshfuji, davem, kuznet, jmorris, kaber, herbert,
eric.dumazet
In-Reply-To: <20131001232534.GM10771@order.stressinduktion.org>
Wed, Oct 02, 2013 at 01:25:34AM CEST, hannes@stressinduktion.org wrote:
>On Tue, Oct 01, 2013 at 11:47:21PM +0200, Hannes Frederic Sowa wrote:
>> The strange thing is that if I don't do the IPV6_MTU setsockopt I don't
>> get an oops.
>
>This is incorrect, it just depends on the size of the writes and on the
>interface mtu.
>
>> IPv4 seems to work without problems, too.
>
>I also get kernel oopses from IPv4 now, too.
I'm not able to trigger this with ipv4. Can you please send strace
output for this as well?
Thanks
^ permalink raw reply
* [PATCH RFC 00/77] Re-design MSI/MSI-X interrupts enablement pattern
From: Alexander Gordeev @ 2013-10-02 10:48 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Alexander Gordeev, Bjorn Helgaas, Ralf Baechle, Michael Ellerman,
Benjamin Herrenschmidt, Martin Schwidefsky, Ingo Molnar,
Tejun Heo, Dan Williams, Andy King, Jon Mason, Matt Porter,
linux-pci-u79uwXL29TY76Z2rM5mHXA,
linux-mips-6z/3iImG2C8G8FEW9MqTrA,
linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
linux390-tA70FqPdS9bQT0dZR+AlfA,
linux-s390-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
linux-ide-u79uwXL29TY76Z2rM5mHXA, iss_storagedev-VXdhtT5mjnY,
linux-nvme-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-rdma-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
e1000-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
linux-driver-h88ZbnxC6KDQT0dZR+AlfA, Solarflare linux maintainers,
"VMware,
This series is against "next" branch in Bjorn's repo:
git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
Currently pci_enable_msi_block() and pci_enable_msix() interfaces
return a error code in case of failure, 0 in case of success and a
positive value which indicates the number of MSI-X/MSI interrupts
that could have been allocated. The latter value should be passed
to a repeated call to the interfaces until a failure or success:
for (i = 0; i < FOO_DRIVER_MAXIMUM_NVEC; i++)
adapter->msix_entries[i].entry = i;
while (nvec >= FOO_DRIVER_MINIMUM_NVEC) {
rc = pci_enable_msix(adapter->pdev,
adapter->msix_entries, nvec);
if (rc > 0)
nvec = rc;
else
return rc;
}
return -ENOSPC;
This technique proved to be confusing and error-prone. Vast share
of device drivers simply fail to follow the described guidelines.
This update converts pci_enable_msix() and pci_enable_msi_block()
interfaces to canonical kernel functions and makes them return a
error code in case of failure or 0 in case of success.
As result, device drivers will cease to use the overcomplicated
repeated fallbacks technique and resort to a straightforward
pattern - determine the number of MSI/MSI-X interrupts required
before calling pci_enable_msi_block() and pci_enable_msix()
interfaces:
rc = pci_msix_table_size(adapter->pdev);
if (rc < 0)
return rc;
nvec = min(nvec, rc);
if (nvec < FOO_DRIVER_MINIMUM_NVEC) {
return -ENOSPC;
for (i = 0; i < nvec; i++)
adapter->msix_entries[i].entry = i;
rc = pci_enable_msix(adapter->pdev,
adapter->msix_entries, nvec);
return rc;
Device drivers will use their knowledge of underlying hardware
to determine the number of MSI/MSI-X interrupts required.
The simplest case would be requesting all available interrupts -
to obtain that value device drivers will use pci_get_msi_cap()
interface for MSI and pci_msix_table_size() for MSI-X.
More complex cases would entail matching device capabilities
to the system environment, i.e. limiting number of hardware
queues (and hence associated MSI/MSI-X interrupts) to the number
of online CPUs.
Device drivers using MSI/MSI-X could be divided in three groups:
- drivers that request a hardcoded number of interrupts;
- drivers that request a number of interrupts using one call to
pci_enable_msix() and then enable MSI/MSI-X using a follow-up
to pci_enable_msix();
- drivers that fully follow the guidelines and repeatedly call
pci_enable_msix() in a loop;
This series converts to the new technique second and third groups.
To simplify device drivers code review I tried to make as little
changes as possible - the scope of this series is an introduction
of the new technique rather than clean-up effort for all drivers
affected.
The testing was very limited - I ensured successful booting on
all affected architectures except MIPS and operation of few
devices with and without pci=nomsi kernel parameter.
There is a ongoing discussion about impact of this update on
PowerPC pSeries platform. I am going to incorporate the outcome
of this discussion into the next version. Yet, the rest of the
platforms and the vast majority of device drivers already can
start getting initial reviews.
Patches 5,6,8 - update of the generic MSI code
Patch 7 - update of architectures affected
Patches 9-77 - bugfixes and updates of device drivers affected
The tree could be found in "pci-next-msi-v1" branch in repo:
https://github.com/a-gordeev/linux.git
Alexander Gordeev (77):
PCI/MSI: Fix return value when populate_msi_sysfs() failed
PCI/MSI/PPC: Fix wrong RTAS error code reporting
PCI/MSI/s390: Fix single MSI only check
PCI/MSI/s390: Remove superfluous check of MSI type
PCI/MSI: Convert pci_msix_table_size() to a public interface
PCI/MSI: Factor out pci_get_msi_cap() interface
PCI/MSI: Re-design MSI/MSI-X interrupts enablement pattern
PCI/MSI: Get rid of pci_enable_msi_block_auto() interface
ahci: Update MSI/MSI-X interrupts enablement code
ahci: Check MRSM bit when multiple MSIs enabled
benet: Return -ENOSPC when not enough MSI-Xs available
benet: Update MSI/MSI-X interrupts enablement code
bna: Update MSI/MSI-X interrupts enablement code
bnx2x: Update MSI/MSI-X interrupts enablement code
bnx2: Update MSI/MSI-X interrupts enablement code
cciss: Update MSI/MSI-X interrupts enablement code
cciss: Update a misleading comment on interrupt usage
cciss: Fallback to single MSI mode in case MSI-X failed
csiostor: Do not call pci_disable_msix() if pci_enable_msix() failed
csiostor: Return -ENOSPC when not enough MSI-X vectors available
csiostor: Update MSI/MSI-X interrupts enablement code
cxgb3: Do not call pci_disable_msix() if pci_enable_msix() failed
cxgb3: Return -ENOSPC when not enough MSI-X vectors available
cxgb3: Update MSI/MSI-X interrupts enablement code
cxgb4: Return -ENOSPC when not enough MSI-X vectors available
cxgb4: Update MSI/MSI-X interrupts enablement code
cxgb4vf: Do not call pci_disable_msix() if pci_enable_msix() failed
cxgb4vf: Return -ENOSPC when not enough MSI-X vectors available
cxgb4vf: Update MSI/MSI-X interrupts enablement code
hpsa: Update a misleading comment on interrupt usage
hpsa: Update MSI/MSI-X interrupts enablement code
hpsa: Fallback to single MSI mode in case MSI-X failed
ioat: Disable MSI-X in case request of IRQ failed
ioat: Update MSI/MSI-X interrupts enablement code
ipr: Do not call pci_disable_msi/msix() if pci_enable_msi/msix()
failed
ipr: Enable MSI-X when IPR_USE_MSIX type is set, not IPR_USE_MSI
ipr: Update MSI/MSI-X interrupts enablement code
ixgbe: Update MSI/MSI-X interrupts enablement code
ixgbevf: Return -ENOSPC when not enough MSI-X vectors available
ixgbevf: Update MSI/MSI-X interrupts enablement code
lpfc: Do not call pci_disable_msix() if pci_enable_msix() failed
lpfc: Update MSI/MSI-X interrupts enablement code
lpfc: Return -ENOSPC when not enough MSI-X vectors available
lpfc: Make MSI-X initialization routine more readable
megaraid: Update MSI/MSI-X interrupts enablement code
mlx4: Update MSI/MSI-X interrupts enablement code
mlx5: Fix memory leak in case not enough MSI-X vectors available
mlx5: Return -ENOSPC when not enough MSI-X vectors available
mlx5: Fix minimum number of MSI-Xs
mlx5: Update MSI/MSI-X interrupts enablement code
mthca: Update MSI/MSI-X interrupts enablement code
niu: Update MSI/MSI-X interrupts enablement code
ntb: Fix missed call to pci_enable_msix()
ntb: Ensure number of MSIs on SNB is enough for the link interrupt
ntb: Update MSI/MSI-X interrupts enablement code
nvme: Update MSI/MSI-X interrupts enablement code
pmcraid: Update MSI/MSI-X interrupts enablement code
qib: Update MSI/MSI-X interrupts enablement code
qla2xxx: Update MSI/MSI-X interrupts enablement code
qlcnic: Return -ENOSPC when not enough MSI-X vectors available
qlogic: Return -EINVAL in case MSI-X is not supported
qlcnic: Remove redundant return operator
qlcnic: Update MSI/MSI-X interrupts enablement code
qlcnic: Make MSI-X initialization routine bit more readable
qlge: Remove a redundant assignment
qlge: Update MSI/MSI-X interrupts enablement code
rapidio: Update MSI/MSI-X interrupts enablement code
sfc: Update MSI/MSI-X interrupts enablement code
tg3: Update MSI/MSI-X interrupts enablement code
vmci: Update MSI/MSI-X interrupts enablement code
vmxnet3: Return -EINVAL if number of requested MSI-Xs is not enough
vmxnet3: Fixup a weird loop exit
vmxnet3: Return -ENOSPC when not enough MSI-X vectors available
vmxnet3: Limit number of rx queues to 1 if per-queue MSI-Xs failed
vmxnet3: Update MSI/MSI-X interrupts enablement code
vxge: Sanitize MSI-X allocation routine error codes
vxge: Update MSI/MSI-X interrupts enablement code
Documentation/PCI/MSI-HOWTO.txt | 123 +++++++++++---------
arch/mips/pci/msi-octeon.c | 2 +-
arch/powerpc/kernel/msi.c | 2 +-
arch/powerpc/platforms/pseries/msi.c | 4 +-
arch/s390/pci/pci.c | 2 +-
arch/x86/kernel/apic/io_apic.c | 2 +-
drivers/ata/ahci.c | 71 ++++++++---
drivers/ata/ahci.h | 1 +
drivers/block/cciss.c | 22 ++--
drivers/block/nvme-core.c | 48 ++++----
drivers/dma/ioat/dma.c | 11 ++-
drivers/infiniband/hw/mthca/mthca_main.c | 16 ++-
drivers/infiniband/hw/qib/qib_pcie.c | 4 -
drivers/misc/vmw_vmci/vmci_guest.c | 22 +++-
drivers/net/ethernet/broadcom/bnx2.c | 27 +++--
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 54 ++++-----
drivers/net/ethernet/broadcom/tg3.c | 24 ++--
drivers/net/ethernet/brocade/bna/bnad.c | 34 +++---
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c | 32 +++---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 62 ++++++----
.../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 49 +++++---
drivers/net/ethernet/emulex/benet/be_main.c | 36 +++---
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 62 +++++-----
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 18 +--
drivers/net/ethernet/mellanox/mlx4/main.c | 17 ++--
drivers/net/ethernet/mellanox/mlx5/core/main.c | 17 ++--
drivers/net/ethernet/neterion/vxge/vxge-main.c | 38 +++----
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 108 +++++++++--------
drivers/net/ethernet/qlogic/qlge/qlge_main.c | 40 +++----
drivers/net/ethernet/sfc/efx.c | 18 ++-
drivers/net/ethernet/sun/niu.c | 20 ++--
drivers/net/vmxnet3/vmxnet3_drv.c | 84 +++++++-------
drivers/ntb/ntb_hw.c | 37 ++----
drivers/ntb/ntb_hw.h | 2 -
drivers/pci/msi.c | 93 +++++----------
drivers/pci/pcie/portdrv_core.c | 2 +
drivers/rapidio/devices/tsi721.c | 27 +++--
drivers/scsi/csiostor/csio_isr.c | 20 ++--
drivers/scsi/hpsa.c | 35 +++---
drivers/scsi/ipr.c | 52 ++++-----
drivers/scsi/lpfc/lpfc_init.c | 40 ++++---
drivers/scsi/megaraid/megaraid_sas_base.c | 20 ++--
drivers/scsi/pmcraid.c | 23 ++--
drivers/scsi/qla2xxx/qla_isr.c | 18 ++-
include/linux/pci.h | 7 +-
45 files changed, 744 insertions(+), 702 deletions(-)
--
1.7.7.6
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH RFC 01/77] PCI/MSI: Fix return value when populate_msi_sysfs() failed
From: Alexander Gordeev @ 2013-10-02 10:48 UTC (permalink / raw)
To: linux-kernel
Cc: Alexander Gordeev, Bjorn Helgaas, Ralf Baechle, Michael Ellerman,
Benjamin Herrenschmidt, Martin Schwidefsky, Ingo Molnar,
Tejun Heo, Dan Williams, Andy King, Jon Mason, Matt Porter,
stable, linux-pci, linux-mips, linuxppc-dev, linux390, linux-s390,
x86, linux-ide, iss_storagedev, linux-nvme, linux-rdma, netdev,
e1000-de
In-Reply-To: <cover.1380703262.git.agordeev@redhat.com>
Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
---
drivers/pci/msi.c | 11 +++++------
1 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index d5f90d6..b43f391 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -719,7 +719,7 @@ static int msix_capability_init(struct pci_dev *dev,
ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
if (ret)
- goto error;
+ goto out_avail;
/*
* Some devices require MSI-X to be enabled before we can touch the
@@ -732,10 +732,8 @@ static int msix_capability_init(struct pci_dev *dev,
msix_program_entries(dev, entries);
ret = populate_msi_sysfs(dev);
- if (ret) {
- ret = 0;
- goto error;
- }
+ if (ret)
+ goto out_free;
/* Set MSI-X enabled bits and unmask the function */
pci_intx_for_msi(dev, 0);
@@ -746,7 +744,7 @@ static int msix_capability_init(struct pci_dev *dev,
return 0;
-error:
+out_avail:
if (ret < 0) {
/*
* If we had some success, report the number of irqs
@@ -763,6 +761,7 @@ error:
ret = avail;
}
+out_free:
free_msi_irqs(dev);
return ret;
--
1.7.7.6
^ permalink raw reply related
* [PATCH RFC 02/77] PCI/MSI/PPC: Fix wrong RTAS error code reporting
From: Alexander Gordeev @ 2013-10-02 10:48 UTC (permalink / raw)
To: linux-kernel
Cc: Alexander Gordeev, Bjorn Helgaas, Ralf Baechle, Michael Ellerman,
Benjamin Herrenschmidt, Martin Schwidefsky, Ingo Molnar,
Tejun Heo, Dan Williams, Andy King, Jon Mason, Matt Porter,
stable, linux-pci, linux-mips, linuxppc-dev, linux390, linux-s390,
x86, linux-ide, iss_storagedev, linux-nvme, linux-rdma, netdev,
e1000-de
In-Reply-To: <cover.1380703262.git.agordeev@redhat.com>
Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
---
arch/powerpc/platforms/pseries/msi.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 6d2f0ab..009ec73 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -467,7 +467,7 @@ again:
list_for_each_entry(entry, &pdev->msi_list, list) {
hwirq = rtas_query_irq_number(pdn, i++);
if (hwirq < 0) {
- pr_debug("rtas_msi: error (%d) getting hwirq\n", rc);
+ pr_debug("rtas_msi: error (%d) getting hwirq\n", hwirq);
return hwirq;
}
--
1.7.7.6
^ permalink raw reply related
* [PATCH RFC 03/77] PCI/MSI/s390: Fix single MSI only check
From: Alexander Gordeev @ 2013-10-02 10:48 UTC (permalink / raw)
To: linux-kernel
Cc: Alexander Gordeev, Bjorn Helgaas, Ralf Baechle, Michael Ellerman,
Benjamin Herrenschmidt, Martin Schwidefsky, Ingo Molnar,
Tejun Heo, Dan Williams, Andy King, Jon Mason, Matt Porter,
stable, linux-pci, linux-mips, linuxppc-dev, linux390, linux-s390,
x86, linux-ide, iss_storagedev, linux-nvme, linux-rdma, netdev,
e1000-de
In-Reply-To: <cover.1380703262.git.agordeev@redhat.com>
Multiple MSIs have never been supported on s390 architecture,
but the platform code fails to report single MSI only.
Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
---
arch/s390/pci/pci.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index f17a834..c79c6e4 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -427,6 +427,8 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec);
if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI)
return -EINVAL;
+ if (type == PCI_CAP_ID_MSI && nvec > 1)
+ return 1;
msi_vecs = min(nvec, ZPCI_MSI_VEC_MAX);
msi_vecs = min_t(unsigned int, msi_vecs, CONFIG_PCI_NR_MSI);
--
1.7.7.6
^ permalink raw reply related
* [PATCH RFC 04/77] PCI/MSI/s390: Remove superfluous check of MSI type
From: Alexander Gordeev @ 2013-10-02 10:48 UTC (permalink / raw)
To: linux-kernel
Cc: Alexander Gordeev, Bjorn Helgaas, Ralf Baechle, Michael Ellerman,
Benjamin Herrenschmidt, Martin Schwidefsky, Ingo Molnar,
Tejun Heo, Dan Williams, Andy King, Jon Mason, Matt Porter,
stable, linux-pci, linux-mips, linuxppc-dev, linux390, linux-s390,
x86, linux-ide, iss_storagedev, linux-nvme, linux-rdma, netdev,
e1000-de
In-Reply-To: <cover.1380703262.git.agordeev@redhat.com>
arch_setup_msi_irqs() hook can only be called from the generic
MSI code which ensures correct MSI type parameter.
Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
---
arch/s390/pci/pci.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index c79c6e4..61a3c2c 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -425,8 +425,6 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
int rc;
pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec);
- if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI)
- return -EINVAL;
if (type == PCI_CAP_ID_MSI && nvec > 1)
return 1;
msi_vecs = min(nvec, ZPCI_MSI_VEC_MAX);
--
1.7.7.6
^ permalink raw reply related
* [PATCH RFC 05/77] PCI/MSI: Convert pci_msix_table_size() to a public interface
From: Alexander Gordeev @ 2013-10-02 10:48 UTC (permalink / raw)
To: linux-kernel
Cc: Alexander Gordeev, Bjorn Helgaas, Ralf Baechle, Michael Ellerman,
Benjamin Herrenschmidt, Martin Schwidefsky, Ingo Molnar,
Tejun Heo, Dan Williams, Andy King, Jon Mason, Matt Porter,
linux-pci, linux-mips, linuxppc-dev, linux390, linux-s390, x86,
linux-ide, iss_storagedev, linux-nvme, linux-rdma, netdev,
e1000-devel
In-Reply-To: <cover.1380703262.git.agordeev@redhat.com>
Make pci_msix_table_size() to return a error code if the device
does not support MSI-X. This update is needed to facilitate a
forthcoming re-design MSI/MSI-X interrupts enabling pattern.
Device drivers will use this interface to obtain maximum number
of MSI-X interrupts the device supports and use that value in
the following call to pci_enable_msix() interface.
Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
---
Documentation/PCI/MSI-HOWTO.txt | 13 +++++++++++++
drivers/pci/msi.c | 5 ++++-
drivers/pci/pcie/portdrv_core.c | 2 ++
3 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt
index a091780..35b2d64 100644
--- a/Documentation/PCI/MSI-HOWTO.txt
+++ b/Documentation/PCI/MSI-HOWTO.txt
@@ -255,6 +255,19 @@ MSI-X Table. This address is mapped by the PCI subsystem, and should not
be accessed directly by the device driver. If the driver wishes to
mask or unmask an interrupt, it should call disable_irq() / enable_irq().
+4.3.4 pci_msix_table_size
+
+int pci_msix_table_size(struct pci_dev *dev)
+
+This function could be used to retrieve number of entries in the device
+MSI-X table.
+
+If this function returns a negative number, it indicates the device is
+not capable of sending MSI-Xs.
+
+If this function returns a positive number, it indicates the maximum
+number of MSI-X interrupt vectors that could be allocated.
+
4.4 Handling devices implementing both MSI and MSI-X capabilities
If a device implements both MSI and MSI-X capabilities, it can
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index b43f391..875c353 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -928,11 +928,12 @@ int pci_msix_table_size(struct pci_dev *dev)
u16 control;
if (!dev->msix_cap)
- return 0;
+ return -EINVAL;
pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
return msix_table_size(control);
}
+EXPORT_SYMBOL(pci_msix_table_size);
/**
* pci_enable_msix - configure device's MSI-X capability structure
@@ -962,6 +963,8 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
return status;
nr_entries = pci_msix_table_size(dev);
+ if (nr_entries < 0)
+ return nr_entries;
if (nvec > nr_entries)
return nr_entries;
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 31063ac..b4d86eb 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -80,6 +80,8 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
u32 reg32;
nr_entries = pci_msix_table_size(dev);
+ if (nr_entries < 0)
+ return nr_entries;
if (!nr_entries)
return -EINVAL;
if (nr_entries > PCIE_PORT_MAX_MSIX_ENTRIES)
--
1.7.7.6
^ permalink raw reply related
* [PATCH RFC 06/77] PCI/MSI: Factor out pci_get_msi_cap() interface
From: Alexander Gordeev @ 2013-10-02 10:48 UTC (permalink / raw)
To: linux-kernel
Cc: Alexander Gordeev, Bjorn Helgaas, Ralf Baechle, Michael Ellerman,
Benjamin Herrenschmidt, Martin Schwidefsky, Ingo Molnar,
Tejun Heo, Dan Williams, Andy King, Jon Mason, Matt Porter,
linux-pci, linux-mips, linuxppc-dev, linux390, linux-s390, x86,
linux-ide, iss_storagedev, linux-nvme, linux-rdma, netdev,
e1000-devel
In-Reply-To: <cover.1380703262.git.agordeev@redhat.com>
This update is needed to facilitate a forthcoming re-design
MSI/MSI-X interrupts enabling pattern.
Device drivers will use this interface to obtain maximum number
of MSI interrupts the device supports and use that value in the
following call to pci_enable_msi_block() interface.
Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
---
Documentation/PCI/MSI-HOWTO.txt | 15 +++++++++++++++
drivers/pci/msi.c | 33 +++++++++++++++++++++------------
include/linux/pci.h | 6 ++++++
3 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt
index 35b2d64..1f37ce2 100644
--- a/Documentation/PCI/MSI-HOWTO.txt
+++ b/Documentation/PCI/MSI-HOWTO.txt
@@ -169,6 +169,21 @@ on any interrupt for which it previously called request_irq().
Failure to do so results in a BUG_ON(), leaving the device with
MSI enabled and thus leaking its vector.
+4.2.5 pci_get_msi_cap
+
+int pci_get_msi_cap(struct pci_dev *dev)
+
+This function could be used to retrieve the number of MSI vectors the
+device requested (via the Multiple Message Capable register). The MSI
+specification only allows the returned value to be a power of two,
+up to a maximum of 2^5 (32).
+
+If this function returns a negative number, it indicates the device is
+not capable of sending MSIs.
+
+If this function returns a positive number, it indicates the maximum
+number of MSI interrupt vectors that could be allocated.
+
4.3 Using MSI-X
The MSI-X capability is much more flexible than the MSI capability.
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 875c353..ca59bfc 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -812,6 +812,21 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)
return 0;
}
+int pci_get_msi_cap(struct pci_dev *dev)
+{
+ int ret;
+ u16 msgctl;
+
+ if (!dev->msi_cap)
+ return -EINVAL;
+
+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);
+ ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
+
+ return ret;
+}
+EXPORT_SYMBOL(pci_get_msi_cap);
+
/**
* pci_enable_msi_block - configure device's MSI capability structure
* @dev: device to configure
@@ -828,13 +843,10 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)
int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
{
int status, maxvec;
- u16 msgctl;
- if (!dev->msi_cap)
- return -EINVAL;
-
- pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);
- maxvec = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
+ maxvec = pci_get_msi_cap(dev);
+ if (maxvec < 0)
+ return maxvec;
if (nvec > maxvec)
return maxvec;
@@ -859,13 +871,10 @@ EXPORT_SYMBOL(pci_enable_msi_block);
int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)
{
int ret, nvec;
- u16 msgctl;
- if (!dev->msi_cap)
- return -EINVAL;
-
- pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);
- ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
+ ret = pci_get_msi_cap(dev);
+ if (ret < 0)
+ return ret;
if (maxvec)
*maxvec = ret;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index da172f9..2fa92ef 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1144,6 +1144,11 @@ struct msix_entry {
#ifndef CONFIG_PCI_MSI
+static inline int pci_get_msi_cap(struct pci_dev *dev)
+{
+ return -1;
+}
+
static inline int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
{
return -1;
@@ -1185,6 +1190,7 @@ static inline int pci_msi_enabled(void)
return 0;
}
#else
+int pci_get_msi_cap(struct pci_dev *dev);
int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec);
void pci_msi_shutdown(struct pci_dev *dev);
--
1.7.7.6
^ permalink raw reply related
* [PATCH RFC 07/77] PCI/MSI: Re-design MSI/MSI-X interrupts enablement pattern
From: Alexander Gordeev @ 2013-10-02 10:48 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Alexander Gordeev, Bjorn Helgaas, Ralf Baechle, Michael Ellerman,
Benjamin Herrenschmidt, Martin Schwidefsky, Ingo Molnar,
Tejun Heo, Dan Williams, Andy King, Jon Mason, Matt Porter,
linux-pci-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-mips-6z/3iImG2C8G8FEW9MqTrA,
linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
linux390-tA70FqPdS9bQT0dZR+AlfA,
linux-s390-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
linux-ide-u79uwXL29TY76Z2rM5mHXA, iss_storagedev-VXdhtT5mjnY,
linux-nvme-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-rdma-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
e1000-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
linux-driver-h88ZbnxC6KDQT0dZR+AlfA,
Solarflare linux maintainers <linux-net-drivers@
In-Reply-To: <cover.1380703262.git.agordeev-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Currently pci_enable_msi_block() and pci_enable_msix() interfaces
return a error code in case of failure, 0 in case of success and a
positive value which indicates the number of MSI-X/MSI interrupts
that could have been allocated. The latter value should be passed
to a repeated call to the interfaces until a failure or success.
This technique proved to be confusing and error-prone. Vast share
of device drivers simply fail to follow the described guidelines.
This update converts pci_enable_msix() and pci_enable_msi_block()
interfaces to canonical kernel functions and makes them return a
error code in case of failure or 0 in case of success.
As result, device drivers will cease to use the overcomplicated
repeated fallbacks technique and resort to a straightforward
pattern - determine the number of MSI/MSI-X interrupts required
before calling pci_enable_msix() and pci_enable_msi_block()
interfaces.
Device drivers will use their knowledge of underlying hardware
to determine the number of MSI/MSI-X interrupts required.
The simplest case would be requesting all available interrupts -
to obtain that value device drivers will use pci_get_msi_cap()
interface for MSI and pci_msix_table_size() for MSI-X.
More complex cases would entail matching device capabilities
with the system environment, i.e. limiting number of hardware
queues (and hence associated MSI/MSI-X interrupts) to the number
of online CPUs.
Suggested-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Alexander Gordeev <agordeev-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
Documentation/PCI/MSI-HOWTO.txt | 71 ++++++++++++++++++---------------
arch/mips/pci/msi-octeon.c | 2 +-
arch/powerpc/kernel/msi.c | 2 +-
arch/powerpc/platforms/pseries/msi.c | 2 +-
arch/s390/pci/pci.c | 2 +-
arch/x86/kernel/apic/io_apic.c | 2 +-
drivers/pci/msi.c | 52 +++++++------------------
7 files changed, 58 insertions(+), 75 deletions(-)
diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt
index 1f37ce2..40abcfb 100644
--- a/Documentation/PCI/MSI-HOWTO.txt
+++ b/Documentation/PCI/MSI-HOWTO.txt
@@ -111,21 +111,27 @@ the device are in the range dev->irq to dev->irq + count - 1.
If this function returns a negative number, it indicates an error and
the driver should not attempt to request any more MSI interrupts for
-this device. If this function returns a positive number, it is
-less than 'count' and indicates the number of interrupts that could have
-been allocated. In neither case is the irq value updated or the device
-switched into MSI mode.
-
-The device driver must decide what action to take if
-pci_enable_msi_block() returns a value less than the number requested.
-For instance, the driver could still make use of fewer interrupts;
-in this case the driver should call pci_enable_msi_block()
-again. Note that it is not guaranteed to succeed, even when the
-'count' has been reduced to the value returned from a previous call to
-pci_enable_msi_block(). This is because there are multiple constraints
-on the number of vectors that can be allocated; pci_enable_msi_block()
-returns as soon as it finds any constraint that doesn't allow the
-call to succeed.
+this device.
+
+Device drivers should normally call pci_get_msi_cap() function before
+calling this function to determine maximum number of MSI interrupts
+a device can send.
+
+A sequence to achieve that might look like:
+
+static int foo_driver_enable_msi(struct foo_adapter *adapter, int nvec)
+{
+ rc = pci_get_msi_cap(adapter->pdev);
+ if (rc < 0)
+ return rc;
+
+ nvec = min(nvec, rc);
+ if (nvec < FOO_DRIVER_MINIMUM_NVEC) {
+ return -ENOSPC;
+
+ rc = pci_enable_msi_block(adapter->pdev, nvec);
+ return rc;
+}
4.2.3 pci_enable_msi_block_auto
@@ -218,9 +224,7 @@ interrupts assigned to the MSI-X vectors so it can free them again later.
If this function returns a negative number, it indicates an error and
the driver should not attempt to allocate any more MSI-X interrupts for
-this device. If it returns a positive number, it indicates the maximum
-number of interrupt vectors that could have been allocated. See example
-below.
+this device.
This function, in contrast with pci_enable_msi(), does not adjust
dev->irq. The device will not generate interrupts for this interrupt
@@ -229,24 +233,27 @@ number once MSI-X is enabled.
Device drivers should normally call this function once per device
during the initialization phase.
-It is ideal if drivers can cope with a variable number of MSI-X interrupts;
-there are many reasons why the platform may not be able to provide the
-exact number that a driver asks for.
+Device drivers should normally call pci_msix_table_size() function before
+calling this function to determine maximum number of MSI-X interrupts
+a device can send.
-A request loop to achieve that might look like:
+A sequence to achieve that might look like:
static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)
{
- while (nvec >= FOO_DRIVER_MINIMUM_NVEC) {
- rc = pci_enable_msix(adapter->pdev,
- adapter->msix_entries, nvec);
- if (rc > 0)
- nvec = rc;
- else
- return rc;
- }
-
- return -ENOSPC;
+ rc = pci_msix_table_size(adapter->pdev);
+ if (rc < 0)
+ return rc;
+
+ nvec = min(nvec, rc);
+ if (nvec < FOO_DRIVER_MINIMUM_NVEC) {
+ return -ENOSPC;
+
+ for (i = 0; i < nvec; i++)
+ adapter->msix_entries[i].entry = i;
+
+ rc = pci_enable_msix(adapter->pdev, adapter->msix_entries, nvec);
+ return rc;
}
4.3.2 pci_disable_msix
diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c
index d37be36..0ee5f4d 100644
--- a/arch/mips/pci/msi-octeon.c
+++ b/arch/mips/pci/msi-octeon.c
@@ -193,7 +193,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
* override arch_setup_msi_irqs()
*/
if (type == PCI_CAP_ID_MSI && nvec > 1)
- return 1;
+ return -EINVAL;
list_for_each_entry(entry, &dev->msi_list, list) {
ret = arch_setup_msi_irq(dev, entry);
diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c
index 8bbc12d..36d70b9 100644
--- a/arch/powerpc/kernel/msi.c
+++ b/arch/powerpc/kernel/msi.c
@@ -22,7 +22,7 @@ int arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
/* PowerPC doesn't support multiple MSI yet */
if (type == PCI_CAP_ID_MSI && nvec > 1)
- return 1;
+ return -EINVAL;
if (ppc_md.msi_check_device) {
pr_debug("msi: Using platform check routine.\n");
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 009ec73..89648c1 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -348,7 +348,7 @@ static int rtas_msi_check_device(struct pci_dev *pdev, int nvec, int type)
quota = msi_quota_for_device(pdev, nvec);
if (quota && quota < nvec)
- return quota;
+ return -ENOSPC;
return 0;
}
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 61a3c2c..45a1875 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -426,7 +426,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec);
if (type == PCI_CAP_ID_MSI && nvec > 1)
- return 1;
+ return -EINVAL;
msi_vecs = min(nvec, ZPCI_MSI_VEC_MAX);
msi_vecs = min_t(unsigned int, msi_vecs, CONFIG_PCI_NR_MSI);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e63a5bd..6126eaf 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3145,7 +3145,7 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
/* Multiple MSI vectors only supported with interrupt remapping */
if (type == PCI_CAP_ID_MSI && nvec > 1)
- return 1;
+ return -EINVAL;
node = dev_to_node(&dev->dev);
irq_want = nr_irqs_gsi;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index ca59bfc..583ace1 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -719,7 +719,7 @@ static int msix_capability_init(struct pci_dev *dev,
ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
if (ret)
- goto out_avail;
+ goto error;
/*
* Some devices require MSI-X to be enabled before we can touch the
@@ -733,7 +733,7 @@ static int msix_capability_init(struct pci_dev *dev,
ret = populate_msi_sysfs(dev);
if (ret)
- goto out_free;
+ goto error;
/* Set MSI-X enabled bits and unmask the function */
pci_intx_for_msi(dev, 0);
@@ -744,24 +744,7 @@ static int msix_capability_init(struct pci_dev *dev,
return 0;
-out_avail:
- if (ret < 0) {
- /*
- * If we had some success, report the number of irqs
- * we succeeded in setting up.
- */
- struct msi_desc *entry;
- int avail = 0;
-
- list_for_each_entry(entry, &dev->msi_list, list) {
- if (entry->irq != 0)
- avail++;
- }
- if (avail != 0)
- ret = avail;
- }
-
-out_free:
+error:
free_msi_irqs(dev);
return ret;
@@ -832,13 +815,11 @@ EXPORT_SYMBOL(pci_get_msi_cap);
* @dev: device to configure
* @nvec: number of interrupts to configure
*
- * Allocate IRQs for a device with the MSI capability.
- * This function returns a negative errno if an error occurs. If it
- * is unable to allocate the number of interrupts requested, it returns
- * the number of interrupts it might be able to allocate. If it successfully
- * allocates at least the number of interrupts requested, it returns 0 and
- * updates the @dev's irq member to the lowest new interrupt number; the
- * other interrupt numbers allocated to this device are consecutive.
+ * Allocate IRQs for a device with the MSI capability. This function returns
+ * a negative errno if an error occurs. If it successfully allocates at least
+ * the number of interrupts requested, it returns 0 and updates the @dev's
+ * irq member to the lowest new interrupt number; the other interrupt numbers
+ * allocated to this device are consecutive.
*/
int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
{
@@ -848,7 +829,7 @@ int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
if (maxvec < 0)
return maxvec;
if (nvec > maxvec)
- return maxvec;
+ return -EINVAL;
status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
if (status)
@@ -879,13 +860,11 @@ int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)
if (maxvec)
*maxvec = ret;
- do {
- nvec = ret;
- ret = pci_enable_msi_block(dev, nvec);
- } while (ret > 0);
-
- if (ret < 0)
+ nvec = ret;
+ ret = pci_enable_msi_block(dev, nvec);
+ if (ret)
return ret;
+
return nvec;
}
EXPORT_SYMBOL(pci_enable_msi_block_auto);
@@ -955,9 +934,6 @@ EXPORT_SYMBOL(pci_msix_table_size);
* MSI-X mode enabled on its hardware device function. A return of zero
* indicates the successful configuration of MSI-X capability structure
* with new allocated MSI-X irqs. A return of < 0 indicates a failure.
- * Or a return of > 0 indicates that driver request is exceeding the number
- * of irqs or MSI-X vectors available. Driver should use the returned value to
- * re-send its request.
**/
int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
{
@@ -975,7 +951,7 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
if (nr_entries < 0)
return nr_entries;
if (nvec > nr_entries)
- return nr_entries;
+ return -EINVAL;
/* Check for any invalid entries */
for (i = 0; i < nvec; i++) {
--
1.7.7.6
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH RFC 08/77] PCI/MSI: Get rid of pci_enable_msi_block_auto() interface
From: Alexander Gordeev @ 2013-10-02 10:48 UTC (permalink / raw)
To: linux-kernel
Cc: Alexander Gordeev, Bjorn Helgaas, Ralf Baechle, Michael Ellerman,
Benjamin Herrenschmidt, Martin Schwidefsky, Ingo Molnar,
Tejun Heo, Dan Williams, Andy King, Jon Mason, Matt Porter,
linux-pci, linux-mips, linuxppc-dev, linux390, linux-s390, x86,
linux-ide, iss_storagedev, linux-nvme, linux-rdma, netdev,
e1000-devel
In-Reply-To: <cover.1380703262.git.agordeev@redhat.com>
As result of recent re-design of MSI/MSI-X interrupts enabling
pattern pci_enable_msi_block_auto() interface became obsolete.
To enable maximum number of MSI interrupts for a device the
driver will first obtain that number from pci_get_msi_cap()
function and then call pci_enable_msi_block() interface.
Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
---
Documentation/PCI/MSI-HOWTO.txt | 30 ++----------------------------
drivers/pci/msi.c | 20 --------------------
include/linux/pci.h | 7 -------
3 files changed, 2 insertions(+), 55 deletions(-)
diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt
index 40abcfb..4d0525f 100644
--- a/Documentation/PCI/MSI-HOWTO.txt
+++ b/Documentation/PCI/MSI-HOWTO.txt
@@ -133,33 +133,7 @@ static int foo_driver_enable_msi(struct foo_adapter *adapter, int nvec)
return rc;
}
-4.2.3 pci_enable_msi_block_auto
-
-int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *count)
-
-This variation on pci_enable_msi() call allows a device driver to request
-the maximum possible number of MSIs. The MSI specification only allows
-interrupts to be allocated in powers of two, up to a maximum of 2^5 (32).
-
-If this function returns a positive number, it indicates that it has
-succeeded and the returned value is the number of allocated interrupts. In
-this case, the function enables MSI on this device and updates dev->irq to
-be the lowest of the new interrupts assigned to it. The other interrupts
-assigned to the device are in the range dev->irq to dev->irq + returned
-value - 1.
-
-If this function returns a negative number, it indicates an error and
-the driver should not attempt to request any more MSI interrupts for
-this device.
-
-If the device driver needs to know the number of interrupts the device
-supports it can pass the pointer count where that number is stored. The
-device driver must decide what action to take if pci_enable_msi_block_auto()
-succeeds, but returns a value less than the number of interrupts supported.
-If the device driver does not need to know the number of interrupts
-supported, it can set the pointer count to NULL.
-
-4.2.4 pci_disable_msi
+4.2.3 pci_disable_msi
void pci_disable_msi(struct pci_dev *dev)
@@ -175,7 +149,7 @@ on any interrupt for which it previously called request_irq().
Failure to do so results in a BUG_ON(), leaving the device with
MSI enabled and thus leaking its vector.
-4.2.5 pci_get_msi_cap
+4.2.4 pci_get_msi_cap
int pci_get_msi_cap(struct pci_dev *dev)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 583ace1..1934519 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -849,26 +849,6 @@ int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
}
EXPORT_SYMBOL(pci_enable_msi_block);
-int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)
-{
- int ret, nvec;
-
- ret = pci_get_msi_cap(dev);
- if (ret < 0)
- return ret;
-
- if (maxvec)
- *maxvec = ret;
-
- nvec = ret;
- ret = pci_enable_msi_block(dev, nvec);
- if (ret)
- return ret;
-
- return nvec;
-}
-EXPORT_SYMBOL(pci_enable_msi_block_auto);
-
void pci_msi_shutdown(struct pci_dev *dev)
{
struct msi_desc *desc;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 2fa92ef..13bf88d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1154,12 +1154,6 @@ static inline int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
return -1;
}
-static inline int
-pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)
-{
- return -1;
-}
-
static inline void pci_msi_shutdown(struct pci_dev *dev)
{ }
static inline void pci_disable_msi(struct pci_dev *dev)
@@ -1192,7 +1186,6 @@ static inline int pci_msi_enabled(void)
#else
int pci_get_msi_cap(struct pci_dev *dev);
int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
-int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec);
void pci_msi_shutdown(struct pci_dev *dev);
void pci_disable_msi(struct pci_dev *dev);
int pci_msix_table_size(struct pci_dev *dev);
--
1.7.7.6
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox