1515#include <linux/ethtool.h>
1616#include <linux/etherdevice.h>
1717#include <linux/mutex.h>
18+ #include <linux/if_vlan.h>
1819
1920#include <asm/vio.h>
2021#include <asm/ldc.h>
@@ -41,6 +42,7 @@ static int __vnet_tx_trigger(struct vnet_port *port, u32 start);
4142
4243/* Ordered from largest major to lowest */
4344static struct vio_version vnet_versions [] = {
45+ { .major = 1 , .minor = 6 },
4446 { .major = 1 , .minor = 0 },
4547};
4648
@@ -67,45 +69,102 @@ static int vnet_send_attr(struct vio_driver_state *vio)
6769 struct vnet_port * port = to_vnet_port (vio );
6870 struct net_device * dev = port -> vp -> dev ;
6971 struct vio_net_attr_info pkt ;
72+ int framelen = ETH_FRAME_LEN ;
7073 int i ;
7174
7275 memset (& pkt , 0 , sizeof (pkt ));
7376 pkt .tag .type = VIO_TYPE_CTRL ;
7477 pkt .tag .stype = VIO_SUBTYPE_INFO ;
7578 pkt .tag .stype_env = VIO_ATTR_INFO ;
7679 pkt .tag .sid = vio_send_sid (vio );
77- pkt .xfer_mode = VIO_DRING_MODE ;
80+ if (vio_version_before (vio , 1 , 2 ))
81+ pkt .xfer_mode = VIO_DRING_MODE ;
82+ else
83+ pkt .xfer_mode = VIO_NEW_DRING_MODE ;
7884 pkt .addr_type = VNET_ADDR_ETHERMAC ;
7985 pkt .ack_freq = 0 ;
8086 for (i = 0 ; i < 6 ; i ++ )
8187 pkt .addr |= (u64 )dev -> dev_addr [i ] << ((5 - i ) * 8 );
82- pkt .mtu = ETH_FRAME_LEN ;
88+ if (vio_version_after (vio , 1 , 3 )) {
89+ if (port -> rmtu ) {
90+ port -> rmtu = min (VNET_MAXPACKET , port -> rmtu );
91+ pkt .mtu = port -> rmtu ;
92+ } else {
93+ port -> rmtu = VNET_MAXPACKET ;
94+ pkt .mtu = port -> rmtu ;
95+ }
96+ if (vio_version_after_eq (vio , 1 , 6 ))
97+ pkt .options = VIO_TX_DRING ;
98+ } else if (vio_version_before (vio , 1 , 3 )) {
99+ pkt .mtu = framelen ;
100+ } else { /* v1.3 */
101+ pkt .mtu = framelen + VLAN_HLEN ;
102+ }
103+
104+ pkt .plnk_updt = PHYSLINK_UPDATE_NONE ;
105+ pkt .cflags = 0 ;
83106
84107 viodbg (HS , "SEND NET ATTR xmode[0x%x] atype[0x%x] addr[%llx] "
85- "ackfreq[%u] mtu[%llu]\n" ,
108+ "ackfreq[%u] plnk_updt[0x%02x] opts[0x%02x] mtu[%llu] "
109+ "cflags[0x%04x] lso_max[%u]\n" ,
86110 pkt .xfer_mode , pkt .addr_type ,
87- (unsigned long long ) pkt .addr ,
88- pkt .ack_freq ,
89- (unsigned long long ) pkt .mtu );
111+ (unsigned long long )pkt .addr ,
112+ pkt .ack_freq , pkt .plnk_updt , pkt .options ,
113+ (unsigned long long )pkt .mtu , pkt .cflags , pkt .ipv4_lso_maxlen );
114+
90115
91116 return vio_ldc_send (vio , & pkt , sizeof (pkt ));
92117}
93118
94119static int handle_attr_info (struct vio_driver_state * vio ,
95120 struct vio_net_attr_info * pkt )
96121{
97- viodbg (HS , "GOT NET ATTR INFO xmode[0x%x] atype[0x%x] addr[%llx] "
98- "ackfreq[%u] mtu[%llu]\n" ,
122+ struct vnet_port * port = to_vnet_port (vio );
123+ u64 localmtu ;
124+ u8 xfer_mode ;
125+
126+ viodbg (HS , "GOT NET ATTR xmode[0x%x] atype[0x%x] addr[%llx] "
127+ "ackfreq[%u] plnk_updt[0x%02x] opts[0x%02x] mtu[%llu] "
128+ " (rmtu[%llu]) cflags[0x%04x] lso_max[%u]\n" ,
99129 pkt -> xfer_mode , pkt -> addr_type ,
100- (unsigned long long ) pkt -> addr ,
101- pkt -> ack_freq ,
102- (unsigned long long ) pkt -> mtu );
130+ (unsigned long long )pkt -> addr ,
131+ pkt -> ack_freq , pkt -> plnk_updt , pkt -> options ,
132+ (unsigned long long )pkt -> mtu , port -> rmtu , pkt -> cflags ,
133+ pkt -> ipv4_lso_maxlen );
103134
104135 pkt -> tag .sid = vio_send_sid (vio );
105136
106- if (pkt -> xfer_mode != VIO_DRING_MODE ||
137+ xfer_mode = pkt -> xfer_mode ;
138+ /* for version < 1.2, VIO_DRING_MODE = 0x3 and no bitmask */
139+ if (vio_version_before (vio , 1 , 2 ) && xfer_mode == VIO_DRING_MODE )
140+ xfer_mode = VIO_NEW_DRING_MODE ;
141+
142+ /* MTU negotiation:
143+ * < v1.3 - ETH_FRAME_LEN exactly
144+ * > v1.3 - MIN(pkt.mtu, VNET_MAXPACKET, port->rmtu) and change
145+ * pkt->mtu for ACK
146+ * = v1.3 - ETH_FRAME_LEN + VLAN_HLEN exactly
147+ */
148+ if (vio_version_before (vio , 1 , 3 )) {
149+ localmtu = ETH_FRAME_LEN ;
150+ } else if (vio_version_after (vio , 1 , 3 )) {
151+ localmtu = port -> rmtu ? port -> rmtu : VNET_MAXPACKET ;
152+ localmtu = min (pkt -> mtu , localmtu );
153+ pkt -> mtu = localmtu ;
154+ } else { /* v1.3 */
155+ localmtu = ETH_FRAME_LEN + VLAN_HLEN ;
156+ }
157+ port -> rmtu = localmtu ;
158+
159+ /* for version >= 1.6, ACK packet mode we support */
160+ if (vio_version_after_eq (vio , 1 , 6 )) {
161+ pkt -> xfer_mode = VIO_NEW_DRING_MODE ;
162+ pkt -> options = VIO_TX_DRING ;
163+ }
164+
165+ if (!(xfer_mode | VIO_NEW_DRING_MODE ) ||
107166 pkt -> addr_type != VNET_ADDR_ETHERMAC ||
108- pkt -> mtu != ETH_FRAME_LEN ) {
167+ pkt -> mtu != localmtu ) {
109168 viodbg (HS , "SEND NET ATTR NACK\n" );
110169
111170 pkt -> tag .stype = VIO_SUBTYPE_NACK ;
@@ -114,7 +173,14 @@ static int handle_attr_info(struct vio_driver_state *vio,
114173
115174 return - ECONNRESET ;
116175 } else {
117- viodbg (HS , "SEND NET ATTR ACK\n" );
176+ viodbg (HS , "SEND NET ATTR ACK xmode[0x%x] atype[0x%x] "
177+ "addr[%llx] ackfreq[%u] plnk_updt[0x%02x] opts[0x%02x] "
178+ "mtu[%llu] (rmtu[%llu]) cflags[0x%04x] lso_max[%u]\n" ,
179+ pkt -> xfer_mode , pkt -> addr_type ,
180+ (unsigned long long )pkt -> addr ,
181+ pkt -> ack_freq , pkt -> plnk_updt , pkt -> options ,
182+ (unsigned long long )pkt -> mtu , port -> rmtu , pkt -> cflags ,
183+ pkt -> ipv4_lso_maxlen );
118184
119185 pkt -> tag .stype = VIO_SUBTYPE_ACK ;
120186
@@ -210,7 +276,7 @@ static int vnet_rx_one(struct vnet_port *port, unsigned int len,
210276 int err ;
211277
212278 err = - EMSGSIZE ;
213- if (unlikely (len < ETH_ZLEN || len > ETH_FRAME_LEN )) {
279+ if (unlikely (len < ETH_ZLEN || len > port -> rmtu )) {
214280 dev -> stats .rx_length_errors ++ ;
215281 goto out_dropped ;
216282 }
@@ -558,8 +624,10 @@ static void vnet_event(void *arg, int event)
558624 vio_link_state_change (vio , event );
559625 spin_unlock_irqrestore (& vio -> lock , flags );
560626
561- if (event == LDC_EVENT_RESET )
627+ if (event == LDC_EVENT_RESET ) {
628+ port -> rmtu = 0 ;
562629 vio_port_up (vio );
630+ }
563631 return ;
564632 }
565633
@@ -1051,8 +1119,8 @@ static int vnet_port_alloc_tx_bufs(struct vnet_port *port)
10511119 void * dring ;
10521120
10531121 for (i = 0 ; i < VNET_TX_RING_SIZE ; i ++ ) {
1054- void * buf = kzalloc (ETH_FRAME_LEN + 8 , GFP_KERNEL );
1055- int map_len = (ETH_FRAME_LEN + 7 ) & ~7 ;
1122+ void * buf = kzalloc (VNET_MAXPACKET + 8 , GFP_KERNEL );
1123+ int map_len = (VNET_MAXPACKET + 7 ) & ~7 ;
10561124
10571125 err = - ENOMEM ;
10581126 if (!buf )
0 commit comments