Переглянути джерело

[intel] Fix operation when physical function has jumbo frames enabled

When jumbo frames are enabled, the Linux ixgbe physical function
driver will disable the virtual function's receive datapath by
default, and will enable it only if the virtual function negotiates
API version 1.1 (or higher) and explicitly selects an MTU.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 роки тому
джерело
коміт
99f87b2338

+ 39
- 2
src/drivers/net/intelvf.c Переглянути файл

@@ -146,8 +146,7 @@ int intelvf_mbox_wait ( struct intel_nic *intel ) {
146 146
  * @v msg		Message buffer
147 147
  * @ret rc		Return status code
148 148
  */
149
-static int intelvf_mbox_msg ( struct intel_nic *intel,
150
-			      union intelvf_msg *msg ) {
149
+int intelvf_mbox_msg ( struct intel_nic *intel, union intelvf_msg *msg ) {
151 150
 	struct intel_mailbox *mbox = &intel->mbox;
152 151
 	uint32_t ctrl;
153 152
 	uint32_t seen = 0;
@@ -301,3 +300,41 @@ int intelvf_mbox_set_mac ( struct intel_nic *intel, const uint8_t *ll_addr ) {
301 300
 
302 301
 	return 0;
303 302
 }
303
+
304
+/**
305
+ * Send set MTU message
306
+ *
307
+ * @v intel		Intel device
308
+ * @v mtu		Maximum packet size
309
+ * @ret rc		Return status code
310
+ */
311
+int intelvf_mbox_set_mtu ( struct intel_nic *intel, size_t mtu ) {
312
+	union intelvf_msg msg;
313
+	int rc;
314
+
315
+	/* Send set MTU message */
316
+	memset ( &msg, 0, sizeof ( msg ) );
317
+	msg.hdr = INTELVF_MSG_TYPE_SET_MTU;
318
+	msg.mtu.mtu = mtu;
319
+	if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
320
+		DBGC ( intel, "INTEL %p set MTU failed: %s\n",
321
+		       intel, strerror ( rc ) );
322
+		return rc;
323
+	}
324
+
325
+	/* Check response */
326
+	if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) != INTELVF_MSG_TYPE_SET_MTU ) {
327
+		DBGC ( intel, "INTEL %p set MTU unexpected response:\n",
328
+		       intel );
329
+		DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
330
+		return -EPROTO;
331
+	}
332
+
333
+	/* Check that we were allowed to set the MTU */
334
+	if ( ! ( msg.hdr & INTELVF_MSG_ACK ) ) {
335
+		DBGC ( intel, "INTEL %p set MTU refused\n", intel );
336
+		return -EPERM;
337
+	}
338
+
339
+	return 0;
340
+}

+ 25
- 0
src/drivers/net/intelvf.h Переглянути файл

@@ -34,6 +34,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
34 34
 /** Set MAC address mailbox message */
35 35
 #define INTELVF_MSG_TYPE_SET_MAC 0x00000002UL
36 36
 
37
+/** Set MTU mailbox message */
38
+#define INTELVF_MSG_TYPE_SET_MTU 0x00000005UL
39
+
37 40
 /** Control ("ping") mailbox message */
38 41
 #define INTELVF_MSG_TYPE_CONTROL 0x00000100UL
39 42
 
@@ -59,12 +62,32 @@ struct intelvf_msg_mac {
59 62
 	uint8_t reserved[ (-ETH_ALEN) & 0x3 ];
60 63
 } __attribute__ (( packed ));
61 64
 
65
+/** Version number mailbox message */
66
+struct intelvf_msg_version {
67
+	/** Message header */
68
+	uint32_t hdr;
69
+	/** API version */
70
+	uint32_t version;
71
+} __attribute__ (( packed ));
72
+
73
+/** MTU mailbox message */
74
+struct intelvf_msg_mtu {
75
+	/** Message header */
76
+	uint32_t hdr;
77
+	/** Maximum packet size */
78
+	uint32_t mtu;
79
+} __attribute__ (( packed ));
80
+
62 81
 /** Mailbox message */
63 82
 union intelvf_msg {
64 83
 	/** Message header */
65 84
 	uint32_t hdr;
66 85
 	/** MAC address message */
67 86
 	struct intelvf_msg_mac mac;
87
+	/** Version number message */
88
+	struct intelvf_msg_version version;
89
+	/** MTU message */
90
+	struct intelvf_msg_mtu mtu;
68 91
 	/** Raw dwords */
69 92
 	uint32_t dword[0];
70 93
 };
@@ -75,10 +98,12 @@ union intelvf_msg {
75 98
  */
76 99
 #define INTELVF_MBOX_MAX_WAIT_MS 500
77 100
 
101
+extern int intelvf_mbox_msg ( struct intel_nic *intel, union intelvf_msg *msg );
78 102
 extern int intelvf_mbox_poll ( struct intel_nic *intel );
79 103
 extern int intelvf_mbox_wait ( struct intel_nic *intel );
80 104
 extern int intelvf_mbox_reset ( struct intel_nic *intel, uint8_t *hw_addr );
81 105
 extern int intelvf_mbox_set_mac ( struct intel_nic *intel,
82 106
 				  const uint8_t *ll_addr );
107
+extern int intelvf_mbox_set_mtu ( struct intel_nic *intel, size_t mtu );
83 108
 
84 109
 #endif /* _INTELVF_H */

+ 64
- 0
src/drivers/net/intelxvf.c Переглянути файл

@@ -109,6 +109,53 @@ static void intelxvf_check_link ( struct net_device *netdev ) {
109 109
 	}
110 110
 }
111 111
 
112
+/******************************************************************************
113
+ *
114
+ * Mailbox messages
115
+ *
116
+ ******************************************************************************
117
+ */
118
+
119
+/**
120
+ * Send negotiate API version message
121
+ *
122
+ * @v intel		Intel device
123
+ * @v version		Requested version
124
+ * @ret rc		Return status code
125
+ */
126
+static int intelxvf_mbox_version ( struct intel_nic *intel,
127
+				   unsigned int version ) {
128
+	union intelvf_msg msg;
129
+	int rc;
130
+
131
+	/* Send set MTU message */
132
+	memset ( &msg, 0, sizeof ( msg ) );
133
+	msg.hdr = INTELXVF_MSG_TYPE_VERSION;
134
+	msg.version.version = version;
135
+	if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
136
+		DBGC ( intel, "INTEL %p negotiate API version failed: %s\n",
137
+		       intel, strerror ( rc ) );
138
+		return rc;
139
+	}
140
+
141
+	/* Check response */
142
+	if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) != INTELXVF_MSG_TYPE_VERSION ){
143
+		DBGC ( intel, "INTEL %p negotiate API version unexpected "
144
+		       "response:\n", intel );
145
+		DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
146
+		return -EPROTO;
147
+	}
148
+
149
+	/* Check that this version is supported */
150
+	if ( ! ( msg.hdr & INTELVF_MSG_ACK ) ) {
151
+		DBGC ( intel, "INTEL %p negotiate API version failed\n",
152
+		       intel );
153
+		return -EPERM;
154
+	}
155
+
156
+	return 0;
157
+}
158
+
112 159
 /******************************************************************************
113 160
  *
114 161
  * Network device interface
@@ -138,6 +185,15 @@ static int intelxvf_open ( struct net_device *netdev ) {
138 185
 		goto err_mbox_reset;
139 186
 	}
140 187
 
188
+	/* Negotiate API version 1.1.  If we do not negotiate at least
189
+	 * this version, then the RX datapath will remain disabled if
190
+	 * the PF has jumbo frames enabled.
191
+	 *
192
+	 * Ignore failures, since the host may not actually support
193
+	 * v1.1.
194
+	 */
195
+	intelxvf_mbox_version ( intel, INTELXVF_MSG_VERSION_1_1 );
196
+
141 197
 	/* Set MAC address */
142 198
 	if ( ( rc = intelvf_mbox_set_mac ( intel, netdev->ll_addr ) ) != 0 ) {
143 199
 		DBGC ( intel, "INTEL %p could not set MAC address: %s\n",
@@ -145,6 +201,13 @@ static int intelxvf_open ( struct net_device *netdev ) {
145 201
 		goto err_mbox_set_mac;
146 202
 	}
147 203
 
204
+	/* Set MTU */
205
+	if ( ( rc = intelvf_mbox_set_mtu ( intel, netdev->max_pkt_len ) ) != 0){
206
+		DBGC ( intel, "INTEL %p could not set MTU %zd: %s\n",
207
+		       intel, netdev->max_pkt_len, strerror ( rc ) );
208
+		goto err_mbox_set_mtu;
209
+	}
210
+
148 211
 	/* Create transmit descriptor ring */
149 212
 	if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 )
150 213
 		goto err_create_tx;
@@ -188,6 +251,7 @@ static int intelxvf_open ( struct net_device *netdev ) {
188 251
  err_create_rx:
189 252
 	intel_destroy_ring ( intel, &intel->tx );
190 253
  err_create_tx:
254
+ err_mbox_set_mtu:
191 255
  err_mbox_set_mac:
192 256
  err_mbox_reset:
193 257
 	intelxvf_reset ( intel );

+ 6
- 0
src/drivers/net/intelxvf.h Переглянути файл

@@ -95,4 +95,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
95 95
 /** Good Packets Transmitted Count High */
96 96
 #define INTELXVF_GOTCH 0x2024
97 97
 
98
+/** Negotiate API version mailbox message */
99
+#define INTELXVF_MSG_TYPE_VERSION 0x00000008UL
100
+
101
+/** API version 1.1 */
102
+#define INTELXVF_MSG_VERSION_1_1 0x00000002UL
103
+
98 104
 #endif /* _INTELXVF_H */

Завантаження…
Відмінити
Зберегти