* Re: team driver MAC NAT
From: Jamal Hadi Salim @ 2013-02-12 15:12 UTC (permalink / raw)
To: Jiri Pirko
Cc: netdev, davem, edumazet, bart.de.schuymer, stephen, pablo, kaber,
netfilter-devel
In-Reply-To: <20130212140247.GB18057@minipsycho.orion>
Jiri,
This would be a good fit for a tc action. This way such a feature can be
used by other netdevs (including plain bridge, and not just team)
The main question is how does the tc action learn about the MAC
addresses that
it needs to convert.
cheers,
jamal
On 13-02-12 09:02 AM, Jiri Pirko wrote:
> Hi all.
>
> I have following situation:
>
> host X ............. eth0 -> br0 <- team0 <- eth2 .............. switch ......... host Z
> host Y ............. eth1 ---^ ^---- eth3 .................^
>
> Now to achieve RX traffic balancing on team0, I have to mangle src mac of
> all outgoing packets. If the packet goes through eth2, src mac will be set to
> eth2 mac, same happens on eth3. I have to magle ARP packets as well.
>
> This would achieve something which might be called "MAC NAT".
>
> To unmangle RXed packets back to the original MAC adresses (of host X and host Y)
> I need to track "connections".
>
> Now the question is: Should this be integrated in netfilter infrastructure?
> I'm thinking something similar to existing conntrack. NF_HOOK will be placed
> in team driver rx/tx functions (similar to what bridge does).
>
> I think this would be nicer than to do it independently just in team driver code.
> Also this MAC NAT (with tracking connections, unlike what bridge MAC NAT does)
> can be probably handy for other purposes as well (not sure what)
>
> Thanks for any suggestions.
>
> Jiri
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" 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
* Re: [PATCH net-next 2/5] gianfar: Cleanup and optimize struct gfar_private
From: Paul Gortmaker @ 2013-02-12 15:11 UTC (permalink / raw)
To: Claudiu Manoil; +Cc: netdev, David S. Miller
In-Reply-To: <1360673237-349-2-git-send-email-claudiu.manoil@freescale.com>
On 13-02-12 07:47 AM, Claudiu Manoil wrote:
> * group run-time critical fields within the 1st cacheline
> followed by the tx|rx_queue reference arrays and the interrupt
> group instances (gfargrp) (all cacheline aligned)
> * change 'padding' from unsigned short to u16
> * clear 20+ byte memory hole
Per prev. mail, it gets harder to see which change is where,
when they are all lumped together like this. For example, it
wasn't obvious to me where the 20 byte hole was. Also, it
doesn't look like you changed the padding, but rather instead
totally re-purposed it, leaving no alignment padding after the
uchar bitfields (where it was originally).
P.
--
> * group releated members
> * push non-critical fields at the end of the struct
>
> Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
> ---
> drivers/net/ethernet/freescale/gianfar.h | 93 +++++++++++++++--------------
> 1 files changed, 48 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
> index 22c2f7a..5304a58 100644
> --- a/drivers/net/ethernet/freescale/gianfar.h
> +++ b/drivers/net/ethernet/freescale/gianfar.h
> @@ -1054,28 +1054,64 @@ enum gfar_errata {
> * the buffer descriptor determines the actual condition.
> */
> struct gfar_private {
> -
> - /* Indicates how many tx, rx queues are enabled */
> - unsigned int num_tx_queues;
> unsigned int num_rx_queues;
> - unsigned int num_grps;
> - unsigned int mode;
> -
> - /* The total tx and rx ring size for the enabled queues */
> - unsigned int total_tx_ring_size;
> - unsigned int total_rx_ring_size;
>
> struct device *dev;
> struct net_device *ndev;
> - struct platform_device *ofdev;
> enum gfar_errata errata;
> + unsigned int rx_buffer_size;
> +
> + u16 padding;
> +
> + /* HW time stamping enabled flag */
> + int hwts_rx_en;
> + int hwts_tx_en;
>
> - struct gfar_priv_grp gfargrp[MAXGROUPS];
> struct gfar_priv_tx_q *tx_queue[MAX_TX_QS];
> struct gfar_priv_rx_q *rx_queue[MAX_RX_QS];
> + struct gfar_priv_grp gfargrp[MAXGROUPS];
> +
> + u32 device_flags;
> +
> + unsigned int mode;
> + unsigned int num_tx_queues;
> + unsigned int num_grps;
> +
> + /* Network Statistics */
> + struct gfar_extra_stats extra_stats;
> +
> + /* PHY stuff */
> + phy_interface_t interface;
> + struct device_node *phy_node;
> + struct device_node *tbi_node;
> + struct phy_device *phydev;
> + struct mii_bus *mii_bus;
> + int oldspeed;
> + int oldduplex;
> + int oldlink;
> +
> + /* Bitfield update lock */
> + spinlock_t bflock;
> +
> + uint32_t msg_enable;
> +
> + struct work_struct reset_task;
> +
> + struct platform_device *ofdev;
> + unsigned char
> + extended_hash:1,
> + bd_stash_en:1,
> + rx_filer_enable:1,
> + /* Wake-on-LAN enabled */
> + wol_en:1,
> + /* Enable priorty based Tx scheduling in Hw */
> + prio_sched_en:1;
> +
> + /* The total tx and rx ring size for the enabled queues */
> + unsigned int total_tx_ring_size;
> + unsigned int total_rx_ring_size;
>
> /* RX per device parameters */
> - unsigned int rx_buffer_size;
> unsigned int rx_stash_size;
> unsigned int rx_stash_index;
>
> @@ -1094,39 +1130,6 @@ struct gfar_private {
> unsigned int fifo_starve;
> unsigned int fifo_starve_off;
>
> - /* Bitfield update lock */
> - spinlock_t bflock;
> -
> - phy_interface_t interface;
> - struct device_node *phy_node;
> - struct device_node *tbi_node;
> - u32 device_flags;
> - unsigned char
> - extended_hash:1,
> - bd_stash_en:1,
> - rx_filer_enable:1,
> - wol_en:1, /* Wake-on-LAN enabled */
> - prio_sched_en:1; /* Enable priorty based Tx scheduling in Hw */
> - unsigned short padding;
> -
> - /* PHY stuff */
> - struct phy_device *phydev;
> - struct mii_bus *mii_bus;
> - int oldspeed;
> - int oldduplex;
> - int oldlink;
> -
> - uint32_t msg_enable;
> -
> - struct work_struct reset_task;
> -
> - /* Network Statistics */
> - struct gfar_extra_stats extra_stats;
> -
> - /* HW time stamping enabled flag */
> - int hwts_rx_en;
> - int hwts_tx_en;
> -
> /*Filer table*/
> unsigned int ftp_rqfpr[MAX_FILER_IDX + 1];
> unsigned int ftp_rqfcr[MAX_FILER_IDX + 1];
>
^ permalink raw reply
* Re: [PATCH 2/2] tcp: fix FIN_WAIT2 timer expression in /proc/net/tcp
From: Eric Dumazet @ 2013-02-12 14:57 UTC (permalink / raw)
To: Toshiaki Makita; +Cc: David S. Miller, netdev
In-Reply-To: <1360673668.10638.14.camel@ubuntu-vm-makita>
On Tue, 2013-02-12 at 21:54 +0900, Toshiaki Makita wrote:
> When tcp_fin_timeout is greater than 60, /proc/net/tcp shows
> FIN_WAIT2 keepalive timer as expires in (tcp_fin_timeout - 60)
> sec. This is confusing because the timer is not for keepalive
> and the socket needs another timewait timer to disappear.
>
> Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
> ---
> net/ipv4/tcp_ipv4.c | 23 +++++++++++++++--------
> net/ipv6/tcp_ipv6.c | 23 +++++++++++++++--------
> 2 files changed, 30 insertions(+), 16 deletions(-)
>
> diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
> index 629937d..32bde0e 100644
> --- a/net/ipv4/tcp_ipv4.c
> +++ b/net/ipv4/tcp_ipv4.c
> @@ -2656,17 +2656,24 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
> int rx_queue;
>
> if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
> - timer_active = 1;
> - timer_expires = icsk->icsk_timeout;
> + timer_active = 1;
> + timer_expires = icsk->icsk_timeout;
> } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
> - timer_active = 4;
> - timer_expires = icsk->icsk_timeout;
> + timer_active = 4;
> + timer_expires = icsk->icsk_timeout;
> } else if (timer_pending(&sk->sk_timer)) {
> - timer_active = 2;
> - timer_expires = sk->sk_timer.expires;
> + if (sk->sk_state == TCP_FIN_WAIT2 && sock_flag(sk, SOCK_DEAD)) {
> + timer_active = 3;
> + timer_expires = sk->sk_timer.expires +
> + (tp->linger2 >= 0 ?
> + TCP_TIMEWAIT_LEN : 0);
> + } else {
> + timer_active = 2;
> + timer_expires = sk->sk_timer.expires;
> + }
> } else {
> - timer_active = 0;
> - timer_expires = jiffies;
> + timer_active = 0;
> + timer_expires = jiffies;
> }
>
I find this patch confusing :
1) Please don't change the indentation for a bug fix
2) You add a new 'active=3' field, that some user space
reading /proc/net/tcp wont expect.
So the changelog is not matching the changes.
^ permalink raw reply
* Re: [PATCH net-next 1/5] gianfar: Cleanup device refs in gfar_private
From: Paul Gortmaker @ 2013-02-12 14:54 UTC (permalink / raw)
To: Claudiu Manoil; +Cc: netdev, David S. Miller
In-Reply-To: <1360673237-349-1-git-send-email-claudiu.manoil@freescale.com>
On 13-02-12 07:47 AM, Claudiu Manoil wrote:
> * remove unused device_node pointer
> * remove duplicate SET_NETDEV_DEV()
> * use device pointer (dev) to simplify the code and to
> avoid double indirections (esp. on the "fast path")
Ideally, when you find yourself making a list within the longlog,
that is a hint that you might want to start making it into
multiple commits, for ease of review. Granted #1 and #2 are
trivial, but #3 probably could be a separate commit. Did you
see any change in the object size or the disassembly when
making change #3?
P.
--
>
> Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
> Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
> ---
> drivers/net/ethernet/freescale/gianfar.c | 29 +++++++++++++----------------
> drivers/net/ethernet/freescale/gianfar.h | 2 +-
> 2 files changed, 14 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
> index 75734bf..096fb5f 100644
> --- a/drivers/net/ethernet/freescale/gianfar.c
> +++ b/drivers/net/ethernet/freescale/gianfar.c
> @@ -231,7 +231,7 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
> dma_addr_t addr;
> int i, j, k;
> struct gfar_private *priv = netdev_priv(ndev);
> - struct device *dev = &priv->ofdev->dev;
> + struct device *dev = priv->dev;
> struct gfar_priv_tx_q *tx_queue = NULL;
> struct gfar_priv_rx_q *rx_queue = NULL;
>
> @@ -668,7 +668,6 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
> return -ENOMEM;
>
> priv = netdev_priv(dev);
> - priv->node = ofdev->dev.of_node;
> priv->ndev = dev;
>
> priv->num_tx_queues = num_tx_qs;
> @@ -1006,7 +1005,7 @@ static int gfar_probe(struct platform_device *ofdev)
> priv = netdev_priv(dev);
> priv->ndev = dev;
> priv->ofdev = ofdev;
> - priv->node = ofdev->dev.of_node;
> + priv->dev = &ofdev->dev;
> SET_NETDEV_DEV(dev, &ofdev->dev);
>
> spin_lock_init(&priv->bflock);
> @@ -1043,8 +1042,6 @@ static int gfar_probe(struct platform_device *ofdev)
> /* Set the dev->base_addr to the gfar reg region */
> dev->base_addr = (unsigned long) regs;
>
> - SET_NETDEV_DEV(dev, &ofdev->dev);
> -
> /* Fill in the dev structure */
> dev->watchdog_timeo = TX_TIMEOUT;
> dev->mtu = 1500;
> @@ -1722,13 +1719,13 @@ static void free_skb_tx_queue(struct gfar_priv_tx_q *tx_queue)
> if (!tx_queue->tx_skbuff[i])
> continue;
>
> - dma_unmap_single(&priv->ofdev->dev, txbdp->bufPtr,
> + dma_unmap_single(priv->dev, txbdp->bufPtr,
> txbdp->length, DMA_TO_DEVICE);
> txbdp->lstatus = 0;
> for (j = 0; j < skb_shinfo(tx_queue->tx_skbuff[i])->nr_frags;
> j++) {
> txbdp++;
> - dma_unmap_page(&priv->ofdev->dev, txbdp->bufPtr,
> + dma_unmap_page(priv->dev, txbdp->bufPtr,
> txbdp->length, DMA_TO_DEVICE);
> }
> txbdp++;
> @@ -1749,8 +1746,8 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
>
> for (i = 0; i < rx_queue->rx_ring_size; i++) {
> if (rx_queue->rx_skbuff[i]) {
> - dma_unmap_single(&priv->ofdev->dev,
> - rxbdp->bufPtr, priv->rx_buffer_size,
> + dma_unmap_single(priv->dev, rxbdp->bufPtr,
> + priv->rx_buffer_size,
> DMA_FROM_DEVICE);
> dev_kfree_skb_any(rx_queue->rx_skbuff[i]);
> rx_queue->rx_skbuff[i] = NULL;
> @@ -1789,7 +1786,7 @@ static void free_skb_resources(struct gfar_private *priv)
> free_skb_rx_queue(rx_queue);
> }
>
> - dma_free_coherent(&priv->ofdev->dev,
> + dma_free_coherent(priv->dev,
> sizeof(struct txbd8) * priv->total_tx_ring_size +
> sizeof(struct rxbd8) * priv->total_rx_ring_size,
> priv->tx_queue[0]->tx_bd_base,
> @@ -2169,7 +2166,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
> if (i == nr_frags - 1)
> lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
>
> - bufaddr = skb_frag_dma_map(&priv->ofdev->dev,
> + bufaddr = skb_frag_dma_map(priv->dev,
> &skb_shinfo(skb)->frags[i],
> 0,
> length,
> @@ -2221,7 +2218,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
> lstatus |= BD_LFLAG(TXBD_TOE);
> }
>
> - txbdp_start->bufPtr = dma_map_single(&priv->ofdev->dev, skb->data,
> + txbdp_start->bufPtr = dma_map_single(priv->dev, skb->data,
> skb_headlen(skb), DMA_TO_DEVICE);
>
> /* If time stamping is requested one additional TxBD must be set up. The
> @@ -2534,7 +2531,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
> } else
> buflen = bdp->length;
>
> - dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
> + dma_unmap_single(priv->dev, bdp->bufPtr,
> buflen, DMA_TO_DEVICE);
>
> if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
> @@ -2553,7 +2550,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
> bdp = next_txbd(bdp, base, tx_ring_size);
>
> for (i = 0; i < frags; i++) {
> - dma_unmap_page(&priv->ofdev->dev, bdp->bufPtr,
> + dma_unmap_page(priv->dev, bdp->bufPtr,
> bdp->length, DMA_TO_DEVICE);
> bdp->lstatus &= BD_LFLAG(TXBD_WRAP);
> bdp = next_txbd(bdp, base, tx_ring_size);
> @@ -2619,7 +2616,7 @@ static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp,
> struct gfar_private *priv = netdev_priv(dev);
> dma_addr_t buf;
>
> - buf = dma_map_single(&priv->ofdev->dev, skb->data,
> + buf = dma_map_single(priv->dev, skb->data,
> priv->rx_buffer_size, DMA_FROM_DEVICE);
> gfar_init_rxbdp(rx_queue, bdp, buf);
> }
> @@ -2784,7 +2781,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
>
> skb = rx_queue->rx_skbuff[rx_queue->skb_currx];
>
> - dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
> + dma_unmap_single(priv->dev, bdp->bufPtr,
> priv->rx_buffer_size, DMA_FROM_DEVICE);
>
> if (unlikely(!(bdp->status & RXBD_ERR) &&
> diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
> index 71793f4..22c2f7a 100644
> --- a/drivers/net/ethernet/freescale/gianfar.h
> +++ b/drivers/net/ethernet/freescale/gianfar.h
> @@ -1065,7 +1065,7 @@ struct gfar_private {
> unsigned int total_tx_ring_size;
> unsigned int total_rx_ring_size;
>
> - struct device_node *node;
> + struct device *dev;
> struct net_device *ndev;
> struct platform_device *ofdev;
> enum gfar_errata errata;
>
^ permalink raw reply
* Matter Of Urgency/Reply!!
From: FEDEX COURIER SERVICE @ 2013-02-12 14:33 UTC (permalink / raw)
Hello, I just want to let you know that I havedeposited your Bank Draft of $850,000.00 United state dollars to the Fedex office contact Mr.Anthony Bright with the below email,for the Shipment of your funds,The Fund is a donation to you from the U.N For your information the VAT and COD have been paid and the only money you will have to pay is the security keeping fee which is $200.00USD.must be paid before shipment. Do contact the FedEx with this Email address is(fedexexpress18@yahoo.cn)Your full:Name:City:State:Age:Sex:Occupation:Country:Phone Number:
^ permalink raw reply
* Re: [PATCH net-next] net: sctp: remove unused multiple cookie keys
From: Neil Horman @ 2013-02-12 14:36 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: davem, linux-sctp, netdev, Vlad Yasevich
In-Reply-To: <c1d3c108e6dc72f14e6251543b9ff826f56f5f78.1360593589.git.dborkman@redhat.com>
On Mon, Feb 11, 2013 at 03:50:07PM +0100, Daniel Borkmann wrote:
> Vlad says: The whole multiple cookie keys code is completely unused
> and has been all this time. Noone uses anything other then the
> secret_key[0] since there is no changeover support anywhere.
>
> Thus, for now clean up its left-over fragments.
>
> Cc: Vlad Yasevich <vyasevic@redhat.com>
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
>
> /* Remove and free the port */
> if (sctp_sk(ep->base.sk)->bind_hash)
> diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
> index e1c5fc2..1063b83 100644
> --- a/net/sctp/sm_make_chunk.c
> +++ b/net/sctp/sm_make_chunk.c
> @@ -1650,8 +1650,8 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
>
> /* Sign the message. */
> sg_init_one(&sg, &cookie->c, bodysize);
> - keylen = SCTP_SECRET_SIZE;
> - key = (char *)ep->secret_key[ep->current_key];
> + keylen = sizeof(ep->secret_key);
> + key = (char *) ep->secret_key;
You can drop the use of they local key variable entirely here.
crypto_hash_setkey takes a u8 * as a key parameter, so you can pass
ep->secret_key directly.
> desc.tfm = sctp_sk(ep->base.sk)->hmac;
> desc.flags = 0;
>
> @@ -1718,9 +1718,9 @@ struct sctp_association *sctp_unpack_cookie(
> goto no_hmac;
>
> /* Check the signature. */
> - keylen = SCTP_SECRET_SIZE;
> sg_init_one(&sg, bear_cookie, bodysize);
> - key = (char *)ep->secret_key[ep->current_key];
> + keylen = sizeof(ep->secret_key);
> + key = (char *) ep->secret_key;
Ditto the above.
Otherwise it looks good.
Neil
^ permalink raw reply
* team driver MAC NAT
From: Jiri Pirko @ 2013-02-12 14:02 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, bart.de.schuymer, stephen, pablo, kaber,
netfilter-devel
Hi all.
I have following situation:
host X ............. eth0 -> br0 <- team0 <- eth2 .............. switch ......... host Z
host Y ............. eth1 ---^ ^---- eth3 .................^
Now to achieve RX traffic balancing on team0, I have to mangle src mac of
all outgoing packets. If the packet goes through eth2, src mac will be set to
eth2 mac, same happens on eth3. I have to magle ARP packets as well.
This would achieve something which might be called "MAC NAT".
To unmangle RXed packets back to the original MAC adresses (of host X and host Y)
I need to track "connections".
Now the question is: Should this be integrated in netfilter infrastructure?
I'm thinking something similar to existing conntrack. NF_HOOK will be placed
in team driver rx/tx functions (similar to what bridge does).
I think this would be nicer than to do it independently just in team driver code.
Also this MAC NAT (with tracking connections, unlike what bridge MAC NAT does)
can be probably handy for other purposes as well (not sure what)
Thanks for any suggestions.
Jiri
^ permalink raw reply
* Re: [patch net-next v5 09/11] act_police: improved accuracy at high rates
From: Jiri Pirko @ 2013-02-12 13:39 UTC (permalink / raw)
To: Jamal Hadi Salim; +Cc: netdev, davem, edumazet, kuznet, j.vimal
In-Reply-To: <511A4429.2040908@mojatatu.com>
Tue, Feb 12, 2013 at 02:31:21PM CET, jhs@mojatatu.com wrote:
>Jiri,
>
>Does this work with your new kernel changes + old tc?
>Some of the kernel fields you have changes that are updated from
>user space with matching 32 bits (eg the pair tcfp_burst which you
>made 64 bits vs user space u32 burst).
>It probably will work - doesnt harm to check on _all_ the fields you
>upgraded to 64 bit.
Yes, this shouldn't be a problem. Userspace passes this values in
struct tc_police *parm and these values are converted into new 64bits
(ticks->ns) ones. Also in dump functions, these are converted back.
Similar changes were made to htb some time ago, I believe that without
issues.
>
>cheers,
>jamal
^ permalink raw reply
* Re: [patch net-next v5 09/11] act_police: improved accuracy at high rates
From: Jamal Hadi Salim @ 2013-02-12 13:31 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, davem, edumazet, kuznet, j.vimal
In-Reply-To: <1360663929-1023-10-git-send-email-jiri@resnulli.us>
Jiri,
Does this work with your new kernel changes + old tc?
Some of the kernel fields you have changes that are updated from
user space with matching 32 bits (eg the pair tcfp_burst which you made
64 bits vs user space u32 burst).
It probably will work - doesnt harm to check on _all_ the fields you
upgraded to 64 bit.
cheers,
jamal
^ permalink raw reply
* [PATCH v3] net: fec_mpc52xx: Read MAC address from device-tree
From: Stefan Roese @ 2013-02-12 13:05 UTC (permalink / raw)
To: netdev; +Cc: linuxppc-dev, Anatolij Gustschin
Until now, the MPC5200 FEC ethernet driver relied upon the bootloader
(U-Boot) to write the MAC address into the ethernet controller
registers. The Linux driver should not rely on such a thing. So
lets read the MAC address from the DT as it should be done here.
The following priority is now used to read the MAC address:
1) First, try OF node MAC address, if not present or invalid, then:
2) Read from MAC address registers, if invalid, then:
3) Log a warning message, and choose a random MAC address.
This fixes a problem with a MPC5200 board that uses the SPL U-Boot
version without FEC initialization before Linux booting for
boot speedup.
Additionally a status line is now be printed upon successful
driver probing, also displaying this MAC address.
Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Anatolij Gustschin <agust@denx.de>
---
v3:
- Use of_get_mac_address() instead of of_get_property()
v2:
- Remove module parameter mpc52xx_fec_mac_addr
- Priority for MAC address probing now is DT, controller regs
If the resulting MAC address is invalid, a random address will
be generated and used with a warning message
- Use "np" variable to simplify the code
drivers/net/ethernet/freescale/fec_mpc52xx.c | 62 +++++++++++++++++-----------
1 file changed, 38 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 817d081..7f91b0c 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -29,6 +29,7 @@
#include <linux/delay.h>
#include <linux/of_device.h>
#include <linux/of_mdio.h>
+#include <linux/of_net.h>
#include <linux/of_platform.h>
#include <linux/netdevice.h>
@@ -76,10 +77,6 @@ static void mpc52xx_fec_stop(struct net_device *dev);
static void mpc52xx_fec_start(struct net_device *dev);
static void mpc52xx_fec_reset(struct net_device *dev);
-static u8 mpc52xx_fec_mac_addr[6];
-module_param_array_named(mac, mpc52xx_fec_mac_addr, byte, NULL, 0);
-MODULE_PARM_DESC(mac, "six hex digits, ie. 0x1,0x2,0xc0,0x01,0xba,0xbe");
-
#define MPC52xx_MESSAGES_DEFAULT ( NETIF_MSG_DRV | NETIF_MSG_PROBE | \
NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP)
static int debug = -1; /* the above default */
@@ -110,15 +107,6 @@ static void mpc52xx_fec_set_paddr(struct net_device *dev, u8 *mac)
out_be32(&fec->paddr2, (*(u16 *)(&mac[4]) << 16) | FEC_PADDR2_TYPE);
}
-static void mpc52xx_fec_get_paddr(struct net_device *dev, u8 *mac)
-{
- struct mpc52xx_fec_priv *priv = netdev_priv(dev);
- struct mpc52xx_fec __iomem *fec = priv->fec;
-
- *(u32 *)(&mac[0]) = in_be32(&fec->paddr1);
- *(u16 *)(&mac[4]) = in_be32(&fec->paddr2) >> 16;
-}
-
static int mpc52xx_fec_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *sock = addr;
@@ -853,6 +841,8 @@ static int mpc52xx_fec_probe(struct platform_device *op)
struct resource mem;
const u32 *prop;
int prop_size;
+ struct device_node *np = op->dev.of_node;
+ const char *mac_addr;
phys_addr_t rx_fifo;
phys_addr_t tx_fifo;
@@ -866,7 +856,7 @@ static int mpc52xx_fec_probe(struct platform_device *op)
priv->ndev = ndev;
/* Reserve FEC control zone */
- rv = of_address_to_resource(op->dev.of_node, 0, &mem);
+ rv = of_address_to_resource(np, 0, &mem);
if (rv) {
printk(KERN_ERR DRIVER_NAME ": "
"Error while parsing device node resource\n" );
@@ -919,7 +909,7 @@ static int mpc52xx_fec_probe(struct platform_device *op)
/* Get the IRQ we need one by one */
/* Control */
- ndev->irq = irq_of_parse_and_map(op->dev.of_node, 0);
+ ndev->irq = irq_of_parse_and_map(np, 0);
/* RX */
priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk);
@@ -927,11 +917,33 @@ static int mpc52xx_fec_probe(struct platform_device *op)
/* TX */
priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk);
- /* MAC address init */
- if (!is_zero_ether_addr(mpc52xx_fec_mac_addr))
- memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6);
- else
- mpc52xx_fec_get_paddr(ndev, ndev->dev_addr);
+ /*
+ * MAC address init:
+ *
+ * First try to read MAC address from DT
+ */
+ mac_addr = of_get_mac_address(np);
+ if (mac_addr) {
+ memcpy(ndev->dev_addr, mac_addr, ETH_ALEN);
+ } else {
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+
+ /*
+ * If the MAC addresse is not provided via DT then read
+ * it back from the controller regs
+ */
+ *(u32 *)(&ndev->dev_addr[0]) = in_be32(&fec->paddr1);
+ *(u16 *)(&ndev->dev_addr[4]) = in_be32(&fec->paddr2) >> 16;
+ }
+
+ /*
+ * Check if the MAC address is valid, if not get a random one
+ */
+ if (!is_valid_ether_addr(ndev->dev_addr)) {
+ eth_hw_addr_random(ndev);
+ dev_warn(&ndev->dev, "using random MAC address %pM\n",
+ ndev->dev_addr);
+ }
priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT);
@@ -942,20 +954,20 @@ static int mpc52xx_fec_probe(struct platform_device *op)
/* Start with safe defaults for link connection */
priv->speed = 100;
priv->duplex = DUPLEX_HALF;
- priv->mdio_speed = ((mpc5xxx_get_bus_frequency(op->dev.of_node) >> 20) / 5) << 1;
+ priv->mdio_speed = ((mpc5xxx_get_bus_frequency(np) >> 20) / 5) << 1;
/* The current speed preconfigures the speed of the MII link */
- prop = of_get_property(op->dev.of_node, "current-speed", &prop_size);
+ prop = of_get_property(np, "current-speed", &prop_size);
if (prop && (prop_size >= sizeof(u32) * 2)) {
priv->speed = prop[0];
priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF;
}
/* If there is a phy handle, then get the PHY node */
- priv->phy_node = of_parse_phandle(op->dev.of_node, "phy-handle", 0);
+ priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
/* the 7-wire property means don't use MII mode */
- if (of_find_property(op->dev.of_node, "fsl,7-wire-mode", NULL)) {
+ if (of_find_property(np, "fsl,7-wire-mode", NULL)) {
priv->seven_wire_mode = 1;
dev_info(&ndev->dev, "using 7-wire PHY mode\n");
}
@@ -970,6 +982,8 @@ static int mpc52xx_fec_probe(struct platform_device *op)
/* We're done ! */
dev_set_drvdata(&op->dev, ndev);
+ printk(KERN_INFO "%s: %s MAC %pM\n",
+ ndev->name, op->dev.of_node->full_name, ndev->dev_addr);
return 0;
--
1.8.1.3
^ permalink raw reply related
* [PATCH 2/2] tcp: fix FIN_WAIT2 timer expression in /proc/net/tcp
From: Toshiaki Makita @ 2013-02-12 12:54 UTC (permalink / raw)
To: David S. Miller, netdev; +Cc: Toshiaki Makita
In-Reply-To: <1360673521.10638.12.camel@ubuntu-vm-makita>
When tcp_fin_timeout is greater than 60, /proc/net/tcp shows
FIN_WAIT2 keepalive timer as expires in (tcp_fin_timeout - 60)
sec. This is confusing because the timer is not for keepalive
and the socket needs another timewait timer to disappear.
Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
---
net/ipv4/tcp_ipv4.c | 23 +++++++++++++++--------
net/ipv6/tcp_ipv6.c | 23 +++++++++++++++--------
2 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 629937d..32bde0e 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2656,17 +2656,24 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
int rx_queue;
if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
- timer_active = 1;
- timer_expires = icsk->icsk_timeout;
+ timer_active = 1;
+ timer_expires = icsk->icsk_timeout;
} else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
- timer_active = 4;
- timer_expires = icsk->icsk_timeout;
+ timer_active = 4;
+ timer_expires = icsk->icsk_timeout;
} else if (timer_pending(&sk->sk_timer)) {
- timer_active = 2;
- timer_expires = sk->sk_timer.expires;
+ if (sk->sk_state == TCP_FIN_WAIT2 && sock_flag(sk, SOCK_DEAD)) {
+ timer_active = 3;
+ timer_expires = sk->sk_timer.expires +
+ (tp->linger2 >= 0 ?
+ TCP_TIMEWAIT_LEN : 0);
+ } else {
+ timer_active = 2;
+ timer_expires = sk->sk_timer.expires;
+ }
} else {
- timer_active = 0;
- timer_expires = jiffies;
+ timer_active = 0;
+ timer_expires = jiffies;
}
if (sk->sk_state == TCP_LISTEN)
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 93825dd..3af4f9d 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1795,17 +1795,24 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
srcp = ntohs(inet->inet_sport);
if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
- timer_active = 1;
- timer_expires = icsk->icsk_timeout;
+ timer_active = 1;
+ timer_expires = icsk->icsk_timeout;
} else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
- timer_active = 4;
- timer_expires = icsk->icsk_timeout;
+ timer_active = 4;
+ timer_expires = icsk->icsk_timeout;
} else if (timer_pending(&sp->sk_timer)) {
- timer_active = 2;
- timer_expires = sp->sk_timer.expires;
+ if (sp->sk_state == TCP_FIN_WAIT2 && sock_flag(sp, SOCK_DEAD)) {
+ timer_active = 3;
+ timer_expires = sp->sk_timer.expires +
+ (tp->linger2 >= 0 ?
+ TCP_TIMEWAIT_LEN : 0);
+ } else {
+ timer_active = 2;
+ timer_expires = sp->sk_timer.expires;
+ }
} else {
- timer_active = 0;
- timer_expires = jiffies;
+ timer_active = 0;
+ timer_expires = jiffies;
}
seq_printf(seq,
--
1.7.1
^ permalink raw reply related
* [PATCH 1/2] tcp: fix too short FIN_WAIT2 time out
From: Toshiaki Makita @ 2013-02-12 12:52 UTC (permalink / raw)
To: David S. Miller, netdev; +Cc: Toshiaki Makita
In-Reply-To: <1360673384.10638.10.camel@ubuntu-vm-makita>
When tcp_fin_timeout is between 60 and 120, FIN_WAIT2 socket
disappears in (tcp_fin_timeout - 60) * 2 sec, which is shorter
than expected.
Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
---
net/ipv4/tcp_timer.c | 8 ++------
1 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index b78aac3..c20e474 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -576,12 +576,8 @@ static void tcp_keepalive_timer (unsigned long data)
if (sk->sk_state == TCP_FIN_WAIT2 && sock_flag(sk, SOCK_DEAD)) {
if (tp->linger2 >= 0) {
- const int tmo = tcp_fin_time(sk) - TCP_TIMEWAIT_LEN;
-
- if (tmo > 0) {
- tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
- goto out;
- }
+ tcp_time_wait(sk, TCP_FIN_WAIT2, TCP_TIMEWAIT_LEN);
+ goto out;
}
tcp_send_active_reset(sk, GFP_ATOMIC);
goto death;
--
1.7.1
^ permalink raw reply related
* [PATCH 0/2] tcp: fix problems when tcp_fin_timeout is greater than 60
From: Toshiaki Makita @ 2013-02-12 12:49 UTC (permalink / raw)
To: David S. Miller, netdev; +Cc: Toshiaki Makita
Hi all,
I found a strange behavior of FIN_WAIT2 timer when tcp_fin_timeout is greater
than 60.
When it is between 60 and 120, if the socket is closed, FIN_WAIT2 keepalive
timer of (tcp_fin_timeout - 60) seconds long starts. After it expires, timewait
timer of (tcp_fin_timeout - 60) seconds long starts again. This takes total time
of (tcp_fin_timeout - 60) * 2 seconds to disappear the FIN_WAIT2 socket, which
is shorter than tcp_fin_timeout.
# sysctl -w net.ipv4.tcp_fin_timeout=63
net.ipv4.tcp_fin_timeout = 63
# while :; do netstat -anot | grep 54321 | grep FIN_WAIT2; sleep 1; done
tcp 0 0 127.0.0.1:43034 127.0.0.1:54321 FIN_WAIT2 keepalive (2.62/0/0)
tcp 0 0 127.0.0.1:43034 127.0.0.1:54321 FIN_WAIT2 keepalive (1.59/0/0)
tcp 0 0 127.0.0.1:43034 127.0.0.1:54321 FIN_WAIT2 keepalive (0.56/0/0)
tcp 0 0 127.0.0.1:43034 127.0.0.1:54321 FIN_WAIT2 timewait (2.61/0/0)
tcp 0 0 127.0.0.1:43034 127.0.0.1:54321 FIN_WAIT2 timewait (1.59/0/0)
tcp 0 0 127.0.0.1:43034 127.0.0.1:54321 FIN_WAIT2 timewait (0.56/0/0)
When it is greater than 120, although timewait timer appears to start from
(tcp_fin_timeout - 60), it expires after 60 seconds elapse in practice.
# sysctl -w net.ipv4.tcp_fin_timeout=150
net.ipv4.tcp_fin_timeout = 150
# while :; do netstat -anot | grep 54321 | grep FIN_WAIT2; sleep 1; done
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 keepalive (90.00/0/0)
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 keepalive (88.97/0/0)
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 keepalive (87.95/0/0)
...
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 keepalive (2.76/0/0)
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 keepalive (1.73/0/0)
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 keepalive (0.70/0/0)
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 timewait (89.68/0/0)
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 timewait (88.66/0/0)
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 timewait (87.63/0/0)
...
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 timewait (32.21/0/0)
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 timewait (31.18/0/0)
tcp 0 0 127.0.0.1:43036 127.0.0.1:54321 FIN_WAIT2 timewait (30.16/0/0)
(no more messages)
This seems to have been so for many years, but I think this behavior is not
desirable because it is confusing and does not match the documents.
Besides, it is also confusing that netstat shows keepalive timer first, and then
shows timewait timer, even though it is necessary to limit resources for the
orphaned socket.
I made patches that fix these problems.
Toshiaki Makita
^ permalink raw reply
* [PATCH net-next 3/5] gianfar: GRO_DROP is unlikely
From: Claudiu Manoil @ 2013-02-12 12:47 UTC (permalink / raw)
To: netdev; +Cc: Paul Gortmaker, David S. Miller
In-Reply-To: <1360673237-349-2-git-send-email-claudiu.manoil@freescale.com>
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
---
drivers/net/ethernet/freescale/gianfar.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 096fb5f..5622134 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2745,7 +2745,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
/* Send the packet up the stack */
ret = napi_gro_receive(napi, skb);
- if (GRO_DROP == ret)
+ if (unlikely(GRO_DROP == ret))
priv->extra_stats.kernel_dropped++;
return 0;
--
1.6.6
^ permalink raw reply related
* [PATCH net-next 2/5] gianfar: Cleanup and optimize struct gfar_private
From: Claudiu Manoil @ 2013-02-12 12:47 UTC (permalink / raw)
To: netdev; +Cc: Paul Gortmaker, David S. Miller
In-Reply-To: <1360673237-349-1-git-send-email-claudiu.manoil@freescale.com>
* group run-time critical fields within the 1st cacheline
followed by the tx|rx_queue reference arrays and the interrupt
group instances (gfargrp) (all cacheline aligned)
* change 'padding' from unsigned short to u16
* clear 20+ byte memory hole
* group releated members
* push non-critical fields at the end of the struct
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
---
drivers/net/ethernet/freescale/gianfar.h | 93 +++++++++++++++--------------
1 files changed, 48 insertions(+), 45 deletions(-)
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 22c2f7a..5304a58 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1054,28 +1054,64 @@ enum gfar_errata {
* the buffer descriptor determines the actual condition.
*/
struct gfar_private {
-
- /* Indicates how many tx, rx queues are enabled */
- unsigned int num_tx_queues;
unsigned int num_rx_queues;
- unsigned int num_grps;
- unsigned int mode;
-
- /* The total tx and rx ring size for the enabled queues */
- unsigned int total_tx_ring_size;
- unsigned int total_rx_ring_size;
struct device *dev;
struct net_device *ndev;
- struct platform_device *ofdev;
enum gfar_errata errata;
+ unsigned int rx_buffer_size;
+
+ u16 padding;
+
+ /* HW time stamping enabled flag */
+ int hwts_rx_en;
+ int hwts_tx_en;
- struct gfar_priv_grp gfargrp[MAXGROUPS];
struct gfar_priv_tx_q *tx_queue[MAX_TX_QS];
struct gfar_priv_rx_q *rx_queue[MAX_RX_QS];
+ struct gfar_priv_grp gfargrp[MAXGROUPS];
+
+ u32 device_flags;
+
+ unsigned int mode;
+ unsigned int num_tx_queues;
+ unsigned int num_grps;
+
+ /* Network Statistics */
+ struct gfar_extra_stats extra_stats;
+
+ /* PHY stuff */
+ phy_interface_t interface;
+ struct device_node *phy_node;
+ struct device_node *tbi_node;
+ struct phy_device *phydev;
+ struct mii_bus *mii_bus;
+ int oldspeed;
+ int oldduplex;
+ int oldlink;
+
+ /* Bitfield update lock */
+ spinlock_t bflock;
+
+ uint32_t msg_enable;
+
+ struct work_struct reset_task;
+
+ struct platform_device *ofdev;
+ unsigned char
+ extended_hash:1,
+ bd_stash_en:1,
+ rx_filer_enable:1,
+ /* Wake-on-LAN enabled */
+ wol_en:1,
+ /* Enable priorty based Tx scheduling in Hw */
+ prio_sched_en:1;
+
+ /* The total tx and rx ring size for the enabled queues */
+ unsigned int total_tx_ring_size;
+ unsigned int total_rx_ring_size;
/* RX per device parameters */
- unsigned int rx_buffer_size;
unsigned int rx_stash_size;
unsigned int rx_stash_index;
@@ -1094,39 +1130,6 @@ struct gfar_private {
unsigned int fifo_starve;
unsigned int fifo_starve_off;
- /* Bitfield update lock */
- spinlock_t bflock;
-
- phy_interface_t interface;
- struct device_node *phy_node;
- struct device_node *tbi_node;
- u32 device_flags;
- unsigned char
- extended_hash:1,
- bd_stash_en:1,
- rx_filer_enable:1,
- wol_en:1, /* Wake-on-LAN enabled */
- prio_sched_en:1; /* Enable priorty based Tx scheduling in Hw */
- unsigned short padding;
-
- /* PHY stuff */
- struct phy_device *phydev;
- struct mii_bus *mii_bus;
- int oldspeed;
- int oldduplex;
- int oldlink;
-
- uint32_t msg_enable;
-
- struct work_struct reset_task;
-
- /* Network Statistics */
- struct gfar_extra_stats extra_stats;
-
- /* HW time stamping enabled flag */
- int hwts_rx_en;
- int hwts_tx_en;
-
/*Filer table*/
unsigned int ftp_rqfpr[MAX_FILER_IDX + 1];
unsigned int ftp_rqfcr[MAX_FILER_IDX + 1];
--
1.6.6
^ permalink raw reply related
* [PATCH net-next 4/5] gianfar: Remove wrong buffer size conditioning to VLAN h/w offload
From: Claudiu Manoil @ 2013-02-12 12:47 UTC (permalink / raw)
To: netdev; +Cc: Paul Gortmaker, David S. Miller
In-Reply-To: <1360673237-349-3-git-send-email-claudiu.manoil@freescale.com>
The controller's ref manual states clearly that when the hw Rx vlan
offload feature is enabled, meaning that the VLEX bit from RCTRL is
correctly enabled, then the hw performs automatic VLAN tag extraction
and deletion from the ethernet frames. So there's no point in trying to
increase the rx buff size when rxvlan is on, as the frame is actually
smaller.
And the Tx vlan hw accel feature (VLINS) has nothing to do with rx buff
size computation.
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
---
drivers/net/ethernet/freescale/gianfar.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 5622134..59fb3bf 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2390,9 +2390,6 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
int oldsize = priv->rx_buffer_size;
int frame_size = new_mtu + ETH_HLEN;
- if (gfar_is_vlan_on(priv))
- frame_size += VLAN_HLEN;
-
if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
netif_err(priv, drv, dev, "Invalid MTU setting\n");
return -EINVAL;
--
1.6.6
^ permalink raw reply related
* [PATCH net-next 1/5] gianfar: Cleanup device refs in gfar_private
From: Claudiu Manoil @ 2013-02-12 12:47 UTC (permalink / raw)
To: netdev; +Cc: Paul Gortmaker, David S. Miller
* remove unused device_node pointer
* remove duplicate SET_NETDEV_DEV()
* use device pointer (dev) to simplify the code and to
avoid double indirections (esp. on the "fast path")
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
---
drivers/net/ethernet/freescale/gianfar.c | 29 +++++++++++++----------------
drivers/net/ethernet/freescale/gianfar.h | 2 +-
2 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 75734bf..096fb5f 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -231,7 +231,7 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
dma_addr_t addr;
int i, j, k;
struct gfar_private *priv = netdev_priv(ndev);
- struct device *dev = &priv->ofdev->dev;
+ struct device *dev = priv->dev;
struct gfar_priv_tx_q *tx_queue = NULL;
struct gfar_priv_rx_q *rx_queue = NULL;
@@ -668,7 +668,6 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
return -ENOMEM;
priv = netdev_priv(dev);
- priv->node = ofdev->dev.of_node;
priv->ndev = dev;
priv->num_tx_queues = num_tx_qs;
@@ -1006,7 +1005,7 @@ static int gfar_probe(struct platform_device *ofdev)
priv = netdev_priv(dev);
priv->ndev = dev;
priv->ofdev = ofdev;
- priv->node = ofdev->dev.of_node;
+ priv->dev = &ofdev->dev;
SET_NETDEV_DEV(dev, &ofdev->dev);
spin_lock_init(&priv->bflock);
@@ -1043,8 +1042,6 @@ static int gfar_probe(struct platform_device *ofdev)
/* Set the dev->base_addr to the gfar reg region */
dev->base_addr = (unsigned long) regs;
- SET_NETDEV_DEV(dev, &ofdev->dev);
-
/* Fill in the dev structure */
dev->watchdog_timeo = TX_TIMEOUT;
dev->mtu = 1500;
@@ -1722,13 +1719,13 @@ static void free_skb_tx_queue(struct gfar_priv_tx_q *tx_queue)
if (!tx_queue->tx_skbuff[i])
continue;
- dma_unmap_single(&priv->ofdev->dev, txbdp->bufPtr,
+ dma_unmap_single(priv->dev, txbdp->bufPtr,
txbdp->length, DMA_TO_DEVICE);
txbdp->lstatus = 0;
for (j = 0; j < skb_shinfo(tx_queue->tx_skbuff[i])->nr_frags;
j++) {
txbdp++;
- dma_unmap_page(&priv->ofdev->dev, txbdp->bufPtr,
+ dma_unmap_page(priv->dev, txbdp->bufPtr,
txbdp->length, DMA_TO_DEVICE);
}
txbdp++;
@@ -1749,8 +1746,8 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
for (i = 0; i < rx_queue->rx_ring_size; i++) {
if (rx_queue->rx_skbuff[i]) {
- dma_unmap_single(&priv->ofdev->dev,
- rxbdp->bufPtr, priv->rx_buffer_size,
+ dma_unmap_single(priv->dev, rxbdp->bufPtr,
+ priv->rx_buffer_size,
DMA_FROM_DEVICE);
dev_kfree_skb_any(rx_queue->rx_skbuff[i]);
rx_queue->rx_skbuff[i] = NULL;
@@ -1789,7 +1786,7 @@ static void free_skb_resources(struct gfar_private *priv)
free_skb_rx_queue(rx_queue);
}
- dma_free_coherent(&priv->ofdev->dev,
+ dma_free_coherent(priv->dev,
sizeof(struct txbd8) * priv->total_tx_ring_size +
sizeof(struct rxbd8) * priv->total_rx_ring_size,
priv->tx_queue[0]->tx_bd_base,
@@ -2169,7 +2166,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (i == nr_frags - 1)
lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
- bufaddr = skb_frag_dma_map(&priv->ofdev->dev,
+ bufaddr = skb_frag_dma_map(priv->dev,
&skb_shinfo(skb)->frags[i],
0,
length,
@@ -2221,7 +2218,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
lstatus |= BD_LFLAG(TXBD_TOE);
}
- txbdp_start->bufPtr = dma_map_single(&priv->ofdev->dev, skb->data,
+ txbdp_start->bufPtr = dma_map_single(priv->dev, skb->data,
skb_headlen(skb), DMA_TO_DEVICE);
/* If time stamping is requested one additional TxBD must be set up. The
@@ -2534,7 +2531,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
} else
buflen = bdp->length;
- dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
+ dma_unmap_single(priv->dev, bdp->bufPtr,
buflen, DMA_TO_DEVICE);
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
@@ -2553,7 +2550,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
bdp = next_txbd(bdp, base, tx_ring_size);
for (i = 0; i < frags; i++) {
- dma_unmap_page(&priv->ofdev->dev, bdp->bufPtr,
+ dma_unmap_page(priv->dev, bdp->bufPtr,
bdp->length, DMA_TO_DEVICE);
bdp->lstatus &= BD_LFLAG(TXBD_WRAP);
bdp = next_txbd(bdp, base, tx_ring_size);
@@ -2619,7 +2616,7 @@ static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp,
struct gfar_private *priv = netdev_priv(dev);
dma_addr_t buf;
- buf = dma_map_single(&priv->ofdev->dev, skb->data,
+ buf = dma_map_single(priv->dev, skb->data,
priv->rx_buffer_size, DMA_FROM_DEVICE);
gfar_init_rxbdp(rx_queue, bdp, buf);
}
@@ -2784,7 +2781,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
skb = rx_queue->rx_skbuff[rx_queue->skb_currx];
- dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
+ dma_unmap_single(priv->dev, bdp->bufPtr,
priv->rx_buffer_size, DMA_FROM_DEVICE);
if (unlikely(!(bdp->status & RXBD_ERR) &&
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 71793f4..22c2f7a 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1065,7 +1065,7 @@ struct gfar_private {
unsigned int total_tx_ring_size;
unsigned int total_rx_ring_size;
- struct device_node *node;
+ struct device *dev;
struct net_device *ndev;
struct platform_device *ofdev;
enum gfar_errata errata;
--
1.6.6
^ permalink raw reply related
* [PATCH net-next 5/5] gianfar: Fix and cleanup Rx FCB handling
From: Claudiu Manoil @ 2013-02-12 12:47 UTC (permalink / raw)
To: netdev; +Cc: Paul Gortmaker, David S. Miller
In-Reply-To: <1360673237-349-4-git-send-email-claudiu.manoil@freescale.com>
NETIF_F_HW_VLAN_TX flag must not condition RxFCB usage.
In the case of RxBD rings, FCBs (Frame Control Block) are inserted by
the eTSEC whenever RCTRL[PRSDEP] is set to a non-zero value. Only one
FCB is inserted per frame (in the buffer pointed to by the RxBD with
bit F set). TOE acceleration for receive is enabled for all rx frames
in this case.
Indroduce the uses_rxfcb field to signal RxFCB insertion in accordance
with the specification above (leading to cleaner, less confusing code).
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
---
drivers/net/ethernet/freescale/gianfar.c | 41 ++++++++++++++---------------
drivers/net/ethernet/freescale/gianfar.h | 1 +
2 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 59fb3bf..3de608c 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -349,6 +349,9 @@ static void gfar_init_mac(struct net_device *ndev)
/* Configure the coalescing support */
gfar_configure_coalescing(priv, 0xFF, 0xFF);
+ /* set this when rx hw offload (TOE) functions are being used */
+ priv->uses_rxfcb = 0;
+
if (priv->rx_filer_enable) {
rctrl |= RCTRL_FILREN;
/* Program the RIR0 reg with the required distribution */
@@ -359,8 +362,10 @@ static void gfar_init_mac(struct net_device *ndev)
if (ndev->flags & IFF_PROMISC)
rctrl |= RCTRL_PROM;
- if (ndev->features & NETIF_F_RXCSUM)
+ if (ndev->features & NETIF_F_RXCSUM) {
rctrl |= RCTRL_CHECKSUMMING;
+ priv->uses_rxfcb = 1;
+ }
if (priv->extended_hash) {
rctrl |= RCTRL_EXTHASH;
@@ -382,11 +387,15 @@ static void gfar_init_mac(struct net_device *ndev)
}
/* Enable HW time stamping if requested from user space */
- if (priv->hwts_rx_en)
+ if (priv->hwts_rx_en) {
rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
+ priv->uses_rxfcb = 1;
+ }
- if (ndev->features & NETIF_F_HW_VLAN_RX)
+ if (ndev->features & NETIF_F_HW_VLAN_RX) {
rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
+ priv->uses_rxfcb = 1;
+ }
/* Init rctrl based on our settings */
gfar_write(®s->rctrl, rctrl);
@@ -505,20 +514,6 @@ void unlock_tx_qs(struct gfar_private *priv)
spin_unlock(&priv->tx_queue[i]->txlock);
}
-static bool gfar_is_vlan_on(struct gfar_private *priv)
-{
- return (priv->ndev->features & NETIF_F_HW_VLAN_RX) ||
- (priv->ndev->features & NETIF_F_HW_VLAN_TX);
-}
-
-/* Returns 1 if incoming frames use an FCB */
-static inline int gfar_uses_fcb(struct gfar_private *priv)
-{
- return gfar_is_vlan_on(priv) ||
- (priv->ndev->features & NETIF_F_RXCSUM) ||
- (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER);
-}
-
static void free_tx_pointers(struct gfar_private *priv)
{
int i;
@@ -2331,10 +2326,13 @@ void gfar_check_rx_parser_mode(struct gfar_private *priv)
tempval = gfar_read(®s->rctrl);
/* If parse is no longer required, then disable parser */
- if (tempval & RCTRL_REQ_PARSER)
+ if (tempval & RCTRL_REQ_PARSER) {
tempval |= RCTRL_PRSDEP_INIT;
- else
+ priv->uses_rxfcb = 1;
+ } else {
tempval &= ~RCTRL_PRSDEP_INIT;
+ priv->uses_rxfcb = 0;
+ }
gfar_write(®s->rctrl, tempval);
}
@@ -2367,6 +2365,7 @@ void gfar_vlan_mode(struct net_device *dev, netdev_features_t features)
tempval = gfar_read(®s->rctrl);
tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
gfar_write(®s->rctrl, tempval);
+ priv->uses_rxfcb = 1;
} else {
/* Disable VLAN tag extraction */
tempval = gfar_read(®s->rctrl);
@@ -2395,7 +2394,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL;
}
- if (gfar_uses_fcb(priv))
+ if (priv->uses_rxfcb)
frame_size += GMAC_FCB_LEN;
frame_size += priv->padding;
@@ -2766,7 +2765,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
bdp = rx_queue->cur_rx;
base = rx_queue->rx_bd_base;
- amount_pull = (gfar_uses_fcb(priv) ? GMAC_FCB_LEN : 0);
+ amount_pull = priv->uses_rxfcb ? GMAC_FCB_LEN : 0;
while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
struct sk_buff *newskb;
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 5304a58..386f1fe 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1061,6 +1061,7 @@ struct gfar_private {
enum gfar_errata errata;
unsigned int rx_buffer_size;
+ u16 uses_rxfcb;
u16 padding;
/* HW time stamping enabled flag */
--
1.6.6
^ permalink raw reply related
* Re: [PATCH v2] net: fec_mpc52xx: Read MAC address from device-tree
From: Timur Tabi @ 2013-02-12 12:36 UTC (permalink / raw)
To: Stefan Roese; +Cc: netdev, linuxppc-dev, Anatolij Gustschin
In-Reply-To: <1360660088-27464-1-git-send-email-sr@denx.de>
On Tue, Feb 12, 2013 at 3:08 AM, Stefan Roese <sr@denx.de> wrote:
> + * First try to read MAC address from DT
> + */
> + p = of_get_property(np, "local-mac-address", NULL);
of_get_mac_address()
^ permalink raw reply
* [PATCH] net: qmi_wwan: add Yota / Megafon M100-1 4g modem
From: Bjørn Mork @ 2013-02-12 12:42 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA, Bjørn Mork
Interface layout:
00 CD-ROM
01 debug COM port
02 AP control port
03 modem
04 usb-ethernet
Bus=01 Lev=02 Prnt=02 Port=01 Cnt=02 Dev#= 4 Spd=480 MxCh= 0
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=0408 ProdID=ea42 Rev= 0.00
S: Manufacturer=Qualcomm, Incorporated
S: Product=Qualcomm CDMA Technologies MSM
S: SerialNumber=353568051xxxxxx
C:* #Ifs= 5 Cfg#= 1 Atr=e0 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms
I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=84(I) Atr=03(Int.) MxPS= 64 Ivl=2ms
E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms
I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=86(I) Atr=03(Int.) MxPS= 64 Ivl=2ms
E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms
Signed-off-by: Bjørn Mork <bjorn-yOkvZcmFvRU@public.gmane.org>
---
drivers/net/usb/qmi_wwan.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index c8e05e2..19d9035 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -411,6 +411,7 @@ static const struct usb_device_id products[] = {
},
/* 3. Combined interface devices matching on interface number */
+ {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */
{QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */
{QMI_FIXED_INTF(0x19d2, 0x0002, 1)},
{QMI_FIXED_INTF(0x19d2, 0x0012, 1)},
--
1.7.10.4
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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
* Re: Issue with Micrel PCI Network Driver.
From: Bjørn Mork @ 2013-02-12 12:40 UTC (permalink / raw)
To: Ben Hutchings; +Cc: joseph.lutz, netdev
In-Reply-To: <1360670867.5374.249.camel@deadeye.wl.decadent.org.uk>
Ben Hutchings <bhutchings@solarflare.com> writes:
> On Tue, 2013-02-12 at 11:10 +0100, Bjørn Mork wrote:
>
>> That should of course be fixed. But this bug should not prevent
>> userspace from renaming the device, should it? Sounds like a userspace
>> application making too many stupid assumptions to me. Does it work for
>> network devices attached to other buses?
>
> It prevents userspace from applying a naming policy that incorporates
> the PCI slot number.
Ah, right. Thanks for explaining. That makes more sense.
Bjørn
^ permalink raw reply
* Re: [patch net-next v5 08/11] act_police: move struct tcf_police to act_police.c
From: Jamal Hadi Salim @ 2013-02-12 12:08 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, davem, edumazet, kuznet, j.vimal
In-Reply-To: <1360663929-1023-9-git-send-email-jiri@resnulli.us>
On 13-02-12 05:12 AM, Jiri Pirko wrote:
> It's not used anywhere else, so move it.
>
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
^ permalink raw reply
* Re: Issue with Micrel PCI Network Driver.
From: Ben Hutchings @ 2013-02-12 12:07 UTC (permalink / raw)
To: Bjørn Mork; +Cc: joseph.lutz, netdev
In-Reply-To: <87halhkfkc.fsf@nemi.mork.no>
On Tue, 2013-02-12 at 11:10 +0100, Bjørn Mork wrote:
> Ben Hutchings <bhutchings@solarflare.com> writes:
> > On Mon, 2013-02-11 at 17:46 +0000, Ben Hutchings wrote:
> >> On Fri, 2013-02-08 at 17:17 -0600, Joseph Lutz wrote:
> >> > I am having an issue with one of the network interface drivers. The
> >> > driver in question is 'drivers/net/ethernet/micrel/ksz884x.c', the
> >> > driver for the Micrel-Kendin device 8841.
> >> > I am trying to get systemd to rename the three network interfaces in my
> >> > embedded atom system. I have one of the interfaces being renamed (an
> >> > Intel Corporation 82574L), but the two Micrel interfaces are not being
> >> > renamed. I traced this down to the driver not populating the
> >> > /sys/devices/pci* information. Instead it places the driver into
> >> > /sys/devices/virtual/net/.
> >> [...]
> >>
> >> Right, this driver doesn't specify the parent device (PCI device) for
> >> the net devices it creates.
> >>
> >> All you should need to is add:
> >> SET_NETDEV_DEV(dev, pdev);
> >> underneath the call to alloc_etherdev().
> >
> > Or rather:
> > SET_NETDEV_DEV(dev, &pdev->dev);
>
>
> That should of course be fixed. But this bug should not prevent
> userspace from renaming the device, should it? Sounds like a userspace
> application making too many stupid assumptions to me. Does it work for
> network devices attached to other buses?
It prevents userspace from applying a naming policy that incorporates
the PCI slot number.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH v2] net: fec_mpc52xx: Read MAC address from device-tree
From: Stefan Roese @ 2013-02-12 12:03 UTC (permalink / raw)
To: Bhushan Bharat-R65777
Cc: netdev@vger.kernel.org, linuxppc-dev@ozlabs.org,
Anatolij Gustschin, David S. Miller
In-Reply-To: <6A3DF150A5B70D4F9B66A25E3F7C888D065A1614@039-SN2MPN1-023.039d.mgd.msft.net>
On 12.02.2013 12:23, Bhushan Bharat-R65777 wrote:
>>> Why we read from MAC registers if Linux should not rely on bootloader?
>>
>> It was suggested by David. Backwards compatibility. Here Davids comment to my
>> original patch which removed this register reading completely:
>>
>> "
>> I don't think this is a conservative enough change.
>>
>> You have to keep the MAC register reading code around, as a backup code path in
>> case the OF device node lacks a MAC address "
>
> Ok,
>
> But this is really a backward compatibility or hiding some bug? My
> thought is that if DT does not have a valid MAC address then it is
> a BUG and should be fixed. Is not it?
Yes. But it can only be fixed in the bootloader then. And some people
might not want to do this or might be unable to do this. So lets keep
this "feature" available for such cases.
BTW: U-Boot traditionally always wrote the MAC address into the FEC
registers. Even if FEC was not used in U-Boot at all. I only noticed
this problem with the new SPL fastbooting U-Boot version, which is
basically a very stripped down U-Boot version directly booting into
Linux (or U-Boot if selected). Here the FEC registers are not touched at
all. And the Linux FEC driver then woke up with an invalid MAC address.
Thanks,
Stefan
^ permalink raw reply
* [PATCHv2 vringh 3/3] caif_virtio: Introduce caif over virtio
From: sjur.brandeland @ 2013-02-12 11:49 UTC (permalink / raw)
To: Rusty Russell, David S. Miller, Ohad Ben-Cohen
Cc: sjur, netdev, virtualization, linux-kernel, Dmitry Tarnyagin,
Linus Walleij, Erwan Yvin, Vikram ARV, Sjur Brændeland,
Ido Yariv
In-Reply-To: <1360669793-6921-1-git-send-email-sjur.brandeland@stericsson.com>
From: Vikram ARV <vikram.arv@stericsson.com>
Add the the Virtio shared memory driver for STE Modems.
caif_virtio is implemented utilizing the virtio framework
for data transport and is managed with the remoteproc frameworks.
The Virtio queue is used for transmitting data to the modem, and
the new vringh implementation is receiving data over the vring.
Signed-off-by: Vikram ARV <vikram.arv@stericsson.com>
Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
cc: David S. Miller <davem@davemloft.net>
cc: Ohad Ben-Cohen <ohad@wizery.com>
cc: Rusty Russell <rusty@rustcorp.com.au>
cc: Ido Yariv <ido@wizery.com>
cc: Erwan Yvin <erwan.yvin@stericsson.com>
---
As mentioned earlier this patch-set will go via Rusty's git.
Changes since V1:
- update to new vringh API,
- use module_virtio_driver macro
- call tasklet_kill from cfv_remove().
Thanks,
Sjur
drivers/net/caif/Kconfig | 8 +
drivers/net/caif/Makefile | 3 +
drivers/net/caif/caif_virtio.c | 547 +++++++++++++++++++++++++++++++++++++++
include/linux/virtio_caif.h | 24 ++
include/uapi/linux/virtio_ids.h | 1 +
5 files changed, 583 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/caif/caif_virtio.c
create mode 100644 include/linux/virtio_caif.h
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index abf4d7a..a8b67e9 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -47,3 +47,11 @@ config CAIF_HSI
The caif low level driver for CAIF over HSI.
Be aware that if you enable this then you also need to
enable a low-level HSI driver.
+
+config CAIF_VIRTIO
+ tristate "CAIF virtio transport driver"
+ depends on CAIF
+ depends on REMOTEPROC
+ default n
+ ---help---
+ The caif driver for CAIF over Virtio.
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index 91dff86..d9ee26a 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -13,3 +13,6 @@ obj-$(CONFIG_CAIF_SHM) += caif_shm.o
# HSI interface
obj-$(CONFIG_CAIF_HSI) += caif_hsi.o
+
+# Virtio interface
+obj-$(CONFIG_CAIF_VIRTIO) += caif_virtio.o
diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c
new file mode 100644
index 0000000..d4f339c
--- /dev/null
+++ b/drivers/net/caif/caif_virtio.c
@@ -0,0 +1,547 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2012
+ * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
+ * Authors: Vicram Arv / vikram.arv@stericsson.com,
+ * Dmitry Tarnyagin / dmitry.tarnyagin@stericsson.com
+ * Sjur Brendeland / sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/module.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/dma-mapping.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/spinlock.h>
+#include <linux/virtio_caif.h>
+#include <linux/virtio_ring.h>
+#include <linux/vringh.h>
+#include <linux/remoteproc.h>
+#include <net/caif/caif_dev.h>
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Vicram Arv <vikram.arv@stericsson.com>");
+MODULE_AUTHOR("Sjur Brendeland <sjur.brandeland@stericsson.com");
+MODULE_DESCRIPTION("Virtio CAIF Driver");
+
+/* Virtio Ring used in receive direction */
+#define RX_RING_INDEX 0
+
+#define CFV_DEFAULT_QUOTA 32
+
+/* struct cfv_napi_contxt - NAPI context info
+ * @riov: IOV holding data read from the ring. Note that riov may
+ * still hold data when cfv_rx_poll() returns.
+ * @head: Last descriptor ID we received from vringh_getdesc_kern.
+ * We use this to put descriptor back on the used ring. USHRT_MAX is
+ * used to indicate invalid head-id.
+ */
+struct cfv_napi_context {
+ struct vringh_kiov riov;
+ unsigned short head;
+};
+
+/* struct cfv_info - Caif Virtio control structure
+ * @cfdev: caif common header
+ * @vdev: Associated virtio device
+ * @vq_rx: rx/downlink virtqueue
+ * @vq_tx: tx/uplink virtqueue
+ * @ndev: associated netdevice
+ * @queued_tx: number of buffers queued in the tx virtqueue
+ * @watermark_tx: indicates number of buffers the tx queue
+ * should shrink to to unblock datapath
+ * @tx_lock: protects vq_tx to allow concurrent senders
+ * @tx_hr: transmit headroom
+ * @rx_hr: receive headroom
+ * @tx_tr: transmit tailroom
+ * @rx_tr: receive tailroom
+ * @mtu: transmit max size
+ * @mru: receive max size
+ */
+struct cfv_info {
+ struct caif_dev_common cfdev;
+ struct virtio_device *vdev;
+ struct vringh *vr_rx;
+ struct virtqueue *vq_tx;
+ struct net_device *ndev;
+ unsigned int queued_tx;
+ unsigned int watermark_tx;
+ /* Protect access to vq_tx */
+ spinlock_t tx_lock;
+ struct tasklet_struct tx_release_tasklet;
+ struct napi_struct napi;
+ struct cfv_napi_context ctx;
+ /* Copied from Virtio config space */
+ u16 tx_hr;
+ u16 rx_hr;
+ u16 tx_tr;
+ u16 rx_tr;
+ u32 mtu;
+ u32 mru;
+};
+
+/* struct token_info - maintains Transmit buffer data handle
+ * @size: size of transmit buffer
+ * @dma_handle: handle to allocated dma device memory area
+ * @vaddr: virtual address mapping to allocated memory area
+ */
+struct token_info {
+ size_t size;
+ u8 *vaddr;
+ dma_addr_t dma_handle;
+};
+
+/* Default if virtio config space is unavailable */
+#define CFV_DEF_MTU_SIZE 4096
+#define CFV_DEF_HEADROOM 32
+#define CFV_DEF_TAILROOM 32
+
+/* Require IP header to be 4-byte aligned. */
+#define IP_HDR_ALIGN 4
+
+static void cfv_release_cb(struct virtqueue *vq_tx)
+{
+ struct cfv_info *cfv = vq_tx->vdev->priv;
+ tasklet_schedule(&cfv->tx_release_tasklet);
+}
+
+/* This is invoked whenever the remote processor completed processing
+ * a TX msg we just sent it, and the buffer is put back to the used ring.
+ */
+static void cfv_release_used_buf(struct virtqueue *vq_tx)
+{
+ struct cfv_info *cfv = vq_tx->vdev->priv;
+ unsigned long flags;
+
+ BUG_ON(vq_tx != cfv->vq_tx);
+ WARN_ON_ONCE(irqs_disabled());
+
+ for (;;) {
+ unsigned int len;
+ struct token_info *buf_info;
+
+ /* Get used buffer from used ring to recycle used descriptors */
+ spin_lock_irqsave(&cfv->tx_lock, flags);
+ buf_info = virtqueue_get_buf(vq_tx, &len);
+
+ if (!buf_info)
+ goto out;
+
+ BUG_ON(!cfv->queued_tx);
+ if (--cfv->queued_tx <= cfv->watermark_tx) {
+ cfv->watermark_tx = 0;
+ netif_tx_wake_all_queues(cfv->ndev);
+ }
+ spin_unlock_irqrestore(&cfv->tx_lock, flags);
+
+ dma_free_coherent(vq_tx->vdev->dev.parent->parent,
+ buf_info->size, buf_info->vaddr,
+ buf_info->dma_handle);
+ kfree(buf_info);
+ }
+ return;
+out:
+ spin_unlock_irqrestore(&cfv->tx_lock, flags);
+}
+
+static struct sk_buff *cfv_alloc_and_copy_skb(int *err,
+ struct cfv_info *cfv,
+ u8 *frm, u32 frm_len)
+{
+ struct sk_buff *skb;
+ u32 cfpkt_len, pad_len;
+
+ *err = 0;
+ /* Verify that packet size with down-link header and mtu size */
+ if (frm_len > cfv->mru || frm_len <= cfv->rx_hr + cfv->rx_tr) {
+ netdev_err(cfv->ndev,
+ "Invalid frmlen:%u mtu:%u hr:%d tr:%d\n",
+ frm_len, cfv->mru, cfv->rx_hr,
+ cfv->rx_tr);
+ *err = -EPROTO;
+ return NULL;
+ }
+
+ cfpkt_len = frm_len - (cfv->rx_hr + cfv->rx_tr);
+
+ pad_len = (unsigned long)(frm + cfv->rx_hr) & (IP_HDR_ALIGN - 1);
+
+ skb = netdev_alloc_skb(cfv->ndev, frm_len + pad_len);
+ if (!skb) {
+ *err = -ENOMEM;
+ return NULL;
+ }
+ /* Reserve space for headers. */
+ skb_reserve(skb, cfv->rx_hr + pad_len);
+
+ memcpy(skb_put(skb, cfpkt_len), frm + cfv->rx_hr, cfpkt_len);
+ return skb;
+}
+
+static int cfv_rx_poll(struct napi_struct *napi, int quota)
+{
+ struct cfv_info *cfv = container_of(napi, struct cfv_info, napi);
+ int rxcnt = 0;
+ int err = 0;
+ void *buf;
+ struct sk_buff *skb;
+ struct vringh_kiov *riov = &cfv->ctx.riov;
+
+ do {
+ skb = NULL;
+ if (riov->i == riov->used) {
+ if (cfv->ctx.head != USHRT_MAX) {
+ vringh_complete_kern(cfv->vr_rx,
+ cfv->ctx.head,
+ 0);
+ cfv->ctx.head = USHRT_MAX;
+ }
+
+ err = vringh_getdesc_kern(
+ cfv->vr_rx,
+ riov,
+ NULL,
+ &cfv->ctx.head,
+ GFP_ATOMIC);
+
+ if (err <= 0)
+ goto out;
+
+ }
+
+ buf = phys_to_virt((unsigned long) riov->iov[riov->i].iov_base);
+ /* TODO: Add check on valid buffer address */
+
+ skb = cfv_alloc_and_copy_skb(&err, cfv, buf,
+ riov->iov[riov->i].iov_len);
+ if (unlikely(err))
+ goto out;
+
+ /* Push received packet up the stack. */
+ skb->protocol = htons(ETH_P_CAIF);
+ skb_reset_mac_header(skb);
+ skb->dev = cfv->ndev;
+ err = netif_receive_skb(skb);
+ if (unlikely(err)) {
+ ++cfv->ndev->stats.rx_dropped;
+ } else {
+ ++cfv->ndev->stats.rx_packets;
+ cfv->ndev->stats.rx_bytes += skb->len;
+ }
+
+ ++riov->i;
+ ++rxcnt;
+ } while (rxcnt < quota);
+
+ return rxcnt;
+
+out:
+ switch (err) {
+ case 0:
+ /* Empty ring, enable notifications and stop NAPI polling */
+ if (!vringh_notify_enable_kern(cfv->vr_rx))
+ napi_complete(napi);
+
+ return rxcnt;
+
+ case -ENOMEM:
+ dev_kfree_skb(skb);
+ /* Stop NAPI poll on OOM, we hope to be polled later */
+ napi_complete(napi);
+ vringh_notify_enable_kern(cfv->vr_rx);
+ break;
+
+ default:
+ /* We're doomed, any modem fault is fatal */
+ netdev_warn(cfv->ndev, "Bad ring, disable device\n");
+ cfv->ndev->stats.rx_dropped = riov->used - riov->i;
+ napi_complete(napi);
+ vringh_notify_disable_kern(cfv->vr_rx);
+ netif_carrier_off(cfv->ndev);
+ break;
+ }
+
+ return rxcnt;
+}
+
+static irqreturn_t cfv_recv(struct virtio_device *vdev, struct vringh *vr_rx)
+{
+ struct cfv_info *cfv = vdev->priv;
+
+ vringh_notify_disable_kern(cfv->vr_rx);
+ napi_schedule(&cfv->napi);
+ return IRQ_HANDLED;
+}
+
+static int cfv_netdev_open(struct net_device *netdev)
+{
+ struct cfv_info *cfv = netdev_priv(netdev);
+
+ netif_carrier_on(netdev);
+ napi_enable(&cfv->napi);
+ return 0;
+}
+
+static int cfv_netdev_close(struct net_device *netdev)
+{
+ struct cfv_info *cfv = netdev_priv(netdev);
+
+ netif_carrier_off(netdev);
+ napi_disable(&cfv->napi);
+ return 0;
+}
+
+static struct token_info *cfv_alloc_and_copy_to_dmabuf(struct cfv_info *cfv,
+ struct sk_buff *skb,
+ struct scatterlist *sg)
+{
+ struct caif_payload_info *info = (void *)&skb->cb;
+ struct token_info *buf_info = NULL;
+ u8 pad_len, hdr_ofs;
+
+ if (unlikely(cfv->tx_hr + skb->len + cfv->tx_tr > cfv->mtu)) {
+ netdev_warn(cfv->ndev, "Invalid packet len (%d > %d)\n",
+ cfv->tx_hr + skb->len + cfv->tx_tr, cfv->mtu);
+ goto err;
+ }
+
+ buf_info = kmalloc(sizeof(struct token_info), GFP_ATOMIC);
+ if (unlikely(!buf_info))
+ goto err;
+
+ /* Make the IP header aligned in tbe buffer */
+ hdr_ofs = cfv->tx_hr + info->hdr_len;
+ pad_len = hdr_ofs & (IP_HDR_ALIGN - 1);
+ buf_info->size = cfv->tx_hr + skb->len + cfv->tx_tr + pad_len;
+
+ if (WARN_ON_ONCE(!cfv->vdev->dev.parent))
+ goto err;
+
+ /* allocate coherent memory for the buffers */
+ buf_info->vaddr =
+ dma_alloc_coherent(cfv->vdev->dev.parent->parent,
+ buf_info->size, &buf_info->dma_handle,
+ GFP_ATOMIC);
+ if (unlikely(!buf_info->vaddr)) {
+ netdev_warn(cfv->ndev,
+ "Out of DMA memory (alloc %zu bytes)\n",
+ buf_info->size);
+ goto err;
+ }
+
+ /* copy skbuf contents to send buffer */
+ skb_copy_bits(skb, 0, buf_info->vaddr + cfv->tx_hr + pad_len, skb->len);
+ sg_init_one(sg, buf_info->vaddr + pad_len,
+ skb->len + cfv->tx_hr + cfv->rx_hr);
+
+ return buf_info;
+err:
+ kfree(buf_info);
+ return NULL;
+}
+
+/* This is invoked whenever the host processor application has sent
+ * up-link data. Send it in the TX VQ avail ring.
+ *
+ * CAIF Virtio sends does not use linked descriptors in the tx direction.
+ */
+static int cfv_netdev_tx(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct cfv_info *cfv = netdev_priv(netdev);
+ struct token_info *buf_info;
+ struct scatterlist sg;
+ unsigned long flags;
+ int ret;
+
+ buf_info = cfv_alloc_and_copy_to_dmabuf(cfv, skb, &sg);
+
+ spin_lock_irqsave(&cfv->tx_lock, flags);
+ if (unlikely(!buf_info))
+ goto flow_off;
+
+ /* Add buffer to avail ring. Flow control below should ensure
+ * that this always succeedes
+ */
+ ret = virtqueue_add_buf(cfv->vq_tx, &sg, 1, 0,
+ buf_info, GFP_ATOMIC);
+
+ if (unlikely(WARN_ON(ret < 0))) {
+ kfree(buf_info);
+ goto flow_off;
+ }
+
+
+ /* update netdev statistics */
+ cfv->queued_tx++;
+ cfv->ndev->stats.tx_packets++;
+ cfv->ndev->stats.tx_bytes += skb->len;
+
+ /* tell the remote processor it has a pending message to read */
+ virtqueue_kick(cfv->vq_tx);
+
+ /* Flow-off check takes into account number of cpus to make sure
+ * virtqueue will not be overfilled in any possible smp conditions.
+ *
+ * Flow-on is triggered when sufficient buffers are freed
+ */
+ if (ret <= num_present_cpus()) {
+flow_off:
+ cfv->watermark_tx = cfv->queued_tx >> 1;
+ netif_tx_stop_all_queues(netdev);
+ }
+
+ spin_unlock_irqrestore(&cfv->tx_lock, flags);
+
+ dev_kfree_skb(skb);
+ tasklet_schedule(&cfv->tx_release_tasklet);
+ return NETDEV_TX_OK;
+}
+
+static void cfv_tx_release_tasklet(unsigned long drv)
+{
+ struct cfv_info *cfv = (struct cfv_info *)drv;
+ cfv_release_used_buf(cfv->vq_tx);
+}
+
+static const struct net_device_ops cfv_netdev_ops = {
+ .ndo_open = cfv_netdev_open,
+ .ndo_stop = cfv_netdev_close,
+ .ndo_start_xmit = cfv_netdev_tx,
+};
+
+static void cfv_netdev_setup(struct net_device *netdev)
+{
+ netdev->netdev_ops = &cfv_netdev_ops;
+ netdev->type = ARPHRD_CAIF;
+ netdev->tx_queue_len = 100;
+ netdev->flags = IFF_POINTOPOINT | IFF_NOARP;
+ netdev->mtu = CFV_DEF_MTU_SIZE;
+ netdev->destructor = free_netdev;
+}
+
+static int cfv_probe(struct virtio_device *vdev)
+{
+ vq_callback_t *vq_cbs = cfv_release_cb;
+ const char *names = "output";
+ const char *cfv_netdev_name = "cfvrt";
+ struct net_device *netdev;
+ struct virtqueue *vqs;
+
+ struct cfv_info *cfv;
+ int err = 0;
+
+ netdev = alloc_netdev(sizeof(struct cfv_info), cfv_netdev_name,
+ cfv_netdev_setup);
+ if (!netdev)
+ return -ENOMEM;
+
+ cfv = netdev_priv(netdev);
+ cfv->vdev = vdev;
+ cfv->ndev = netdev;
+
+ spin_lock_init(&cfv->tx_lock);
+
+ cfv->vr_rx = rproc_virtio_new_vringh(vdev, RX_RING_INDEX, cfv_recv);
+ if (!cfv->vr_rx)
+ goto free_cfv;
+
+ /* Get the TX (uplink) virtque */
+ err = vdev->config->find_vqs(vdev, 1, &vqs, &vq_cbs, &names);
+ if (err)
+ goto free_cfv;
+
+ cfv->vq_tx = vqs;
+
+#define GET_VIRTIO_CONFIG_OPS(_v, _var, _f) \
+ ((_v)->config->get(_v, offsetof(struct virtio_caif_transf_config, _f), \
+ &_var, \
+ FIELD_SIZEOF(struct virtio_caif_transf_config, _f)))
+
+ if (vdev->config->get) {
+ GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_hr, headroom);
+ GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_hr, headroom);
+ GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_tr, tailroom);
+ GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_tr, tailroom);
+ GET_VIRTIO_CONFIG_OPS(vdev, cfv->mtu, mtu);
+ GET_VIRTIO_CONFIG_OPS(vdev, cfv->mru, mtu);
+ } else {
+ cfv->tx_hr = CFV_DEF_HEADROOM;
+ cfv->rx_hr = CFV_DEF_HEADROOM;
+ cfv->tx_tr = CFV_DEF_TAILROOM;
+ cfv->rx_tr = CFV_DEF_TAILROOM;
+ cfv->mtu = CFV_DEF_MTU_SIZE;
+ cfv->mru = CFV_DEF_MTU_SIZE;
+ }
+
+ netdev->needed_headroom = cfv->tx_hr;
+ netdev->needed_tailroom = cfv->tx_tr;
+
+ /* Subtract needed tailroom from MTU to ensure enough room */
+ netdev->mtu = cfv->mtu - cfv->tx_tr;
+
+ vdev->priv = cfv;
+
+ vringh_iov_init(&cfv->ctx.riov, NULL, 0);
+ cfv->ctx.head = USHRT_MAX;
+
+ netif_napi_add(netdev, &cfv->napi, cfv_rx_poll, CFV_DEFAULT_QUOTA);
+ tasklet_init(&cfv->tx_release_tasklet,
+ cfv_tx_release_tasklet,
+ (unsigned long)cfv);
+
+ netif_carrier_off(netdev);
+
+ /* register Netdev */
+ err = register_netdev(netdev);
+ if (err) {
+ dev_err(&vdev->dev, "Unable to register netdev (%d)\n", err);
+ goto vqs_del;
+ }
+
+ /* tell the remote processor it can start sending messages */
+ rproc_virtio_kick_vringh(vdev, RX_RING_INDEX);
+
+ return 0;
+
+vqs_del:
+ vdev->config->del_vqs(cfv->vdev);
+free_cfv:
+ free_netdev(netdev);
+ return err;
+}
+
+static void cfv_remove(struct virtio_device *vdev)
+{
+ struct cfv_info *cfv = vdev->priv;
+
+ tasklet_kill(&cfv->tx_release_tasklet);
+ vringh_iov_cleanup(&cfv->ctx.riov);
+ vdev->config->reset(vdev);
+ rproc_virtio_del_vringh(vdev, RX_RING_INDEX);
+ cfv->vr_rx = NULL;
+ vdev->config->del_vqs(cfv->vdev);
+ unregister_netdev(cfv->ndev);
+}
+
+static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_CAIF, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+static unsigned int features[] = {
+};
+
+static struct virtio_driver caif_virtio_driver = {
+ .feature_table = features,
+ .feature_table_size = ARRAY_SIZE(features),
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .id_table = id_table,
+ .probe = cfv_probe,
+ .remove = cfv_remove,
+};
+
+module_virtio_driver(caif_virtio_driver);
+MODULE_DEVICE_TABLE(virtio, id_table);
diff --git a/include/linux/virtio_caif.h b/include/linux/virtio_caif.h
new file mode 100644
index 0000000..5d2d312
--- /dev/null
+++ b/include/linux/virtio_caif.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2012
+ * Author: Sjur Brændeland <sjur.brandeland@stericsson.com>
+ *
+ * This header is BSD licensed so
+ * anyone can use the definitions to implement compatible remote processors
+ */
+
+#ifndef VIRTIO_CAIF_H
+#define VIRTIO_CAIF_H
+
+#include <linux/types.h>
+struct virtio_caif_transf_config {
+ u16 headroom;
+ u16 tailroom;
+ u32 mtu;
+ u8 reserved[4];
+};
+
+struct virtio_caif_config {
+ struct virtio_caif_transf_config uplink, downlink;
+ u8 reserved[8];
+};
+#endif
diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h
index a7630d0..284fc3a 100644
--- a/include/uapi/linux/virtio_ids.h
+++ b/include/uapi/linux/virtio_ids.h
@@ -38,5 +38,6 @@
#define VIRTIO_ID_SCSI 8 /* virtio scsi */
#define VIRTIO_ID_9P 9 /* 9p virtio console */
#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */
+#define VIRTIO_ID_CAIF 12 /* Virtio caif */
#endif /* _LINUX_VIRTIO_IDS_H */
--
1.7.5.4
^ 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