Browse Source

[intelxl] Allow admin queues to be reinitialised

A virtual function reset is triggered via an admin queue command and
will reset the admin queue configuration registers.  Allow the admin
queues to be reinitialised after such a reset, without requiring the
overhead (and potential failure paths) of freeing and reallocating the
queues.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 5 years ago
parent
commit
7b68c310f9
1 changed files with 85 additions and 41 deletions
  1. 85
    41
      src/drivers/net/intelxl.c

+ 85
- 41
src/drivers/net/intelxl.c View File

45
  *
45
  *
46
  */
46
  */
47
 
47
 
48
+static void intelxl_reopen_admin ( struct intelxl_nic *intelxl );
49
+
48
 /******************************************************************************
50
 /******************************************************************************
49
  *
51
  *
50
  * Device reset
52
  * Device reset
133
 };
135
 };
134
 
136
 
135
 /**
137
 /**
136
- * Create admin queue
138
+ * Allocate admin queue
137
  *
139
  *
138
  * @v intelxl		Intel device
140
  * @v intelxl		Intel device
139
  * @v admin		Admin queue
141
  * @v admin		Admin queue
140
  * @ret rc		Return status code
142
  * @ret rc		Return status code
141
  */
143
  */
142
-static int intelxl_create_admin ( struct intelxl_nic *intelxl,
143
-				  struct intelxl_admin *admin ) {
144
+static int intelxl_alloc_admin ( struct intelxl_nic *intelxl,
145
+				 struct intelxl_admin *admin ) {
144
 	size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
146
 	size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
145
 	size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
147
 	size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
146
-	const struct intelxl_admin_offsets *regs = admin->regs;
147
-	void *admin_regs = ( intelxl->regs + admin->base );
148
-	physaddr_t address;
149
 
148
 
150
 	/* Allocate admin queue */
149
 	/* Allocate admin queue */
151
 	admin->buf = malloc_dma ( ( buf_len + len ), INTELXL_ALIGN );
150
 	admin->buf = malloc_dma ( ( buf_len + len ), INTELXL_ALIGN );
153
 		return -ENOMEM;
152
 		return -ENOMEM;
154
 	admin->desc = ( ( ( void * ) admin->buf ) + buf_len );
153
 	admin->desc = ( ( ( void * ) admin->buf ) + buf_len );
155
 
154
 
155
+	DBGC ( intelxl, "INTELXL %p A%cQ is at [%08llx,%08llx) buf "
156
+	       "[%08llx,%08llx)\n", intelxl,
157
+	       ( ( admin == &intelxl->command ) ? 'T' : 'R' ),
158
+	       ( ( unsigned long long ) virt_to_bus ( admin->desc ) ),
159
+	       ( ( unsigned long long ) ( virt_to_bus ( admin->desc ) + len ) ),
160
+	       ( ( unsigned long long ) virt_to_bus ( admin->buf ) ),
161
+	       ( ( unsigned long long ) ( virt_to_bus ( admin->buf ) +
162
+					  buf_len ) ) );
163
+	return 0;
164
+}
165
+
166
+/**
167
+ * Enable admin queue
168
+ *
169
+ * @v intelxl		Intel device
170
+ * @v admin		Admin queue
171
+ */
172
+static void intelxl_enable_admin ( struct intelxl_nic *intelxl,
173
+				   struct intelxl_admin *admin ) {
174
+	size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
175
+	const struct intelxl_admin_offsets *regs = admin->regs;
176
+	void *admin_regs = ( intelxl->regs + admin->base );
177
+	physaddr_t address;
178
+
156
 	/* Initialise admin queue */
179
 	/* Initialise admin queue */
157
 	memset ( admin->desc, 0, len );
180
 	memset ( admin->desc, 0, len );
158
 
181
 
177
 	writel ( ( INTELXL_ADMIN_LEN_LEN ( INTELXL_ADMIN_NUM_DESC ) |
200
 	writel ( ( INTELXL_ADMIN_LEN_LEN ( INTELXL_ADMIN_NUM_DESC ) |
178
 		   INTELXL_ADMIN_LEN_ENABLE ),
201
 		   INTELXL_ADMIN_LEN_ENABLE ),
179
 		 admin_regs + regs->len );
202
 		 admin_regs + regs->len );
180
-
181
-	DBGC ( intelxl, "INTELXL %p A%cQ is at [%08llx,%08llx) buf "
182
-	       "[%08llx,%08llx)\n", intelxl,
183
-	       ( ( admin == &intelxl->command ) ? 'T' : 'R' ),
184
-	       ( ( unsigned long long ) address ),
185
-	       ( ( unsigned long long ) address + len ),
186
-	       ( ( unsigned long long ) virt_to_bus ( admin->buf ) ),
187
-	       ( ( unsigned long long ) ( virt_to_bus ( admin->buf ) +
188
-					  buf_len ) ) );
189
-	return 0;
190
 }
203
 }
191
 
204
 
192
 /**
205
 /**
193
- * Destroy admin queue
206
+ * Disable admin queue
194
  *
207
  *
195
  * @v intelxl		Intel device
208
  * @v intelxl		Intel device
196
  * @v admin		Admin queue
209
  * @v admin		Admin queue
197
  */
210
  */
198
-static void intelxl_destroy_admin ( struct intelxl_nic *intelxl,
211
+static void intelxl_disable_admin ( struct intelxl_nic *intelxl,
199
 				    struct intelxl_admin *admin ) {
212
 				    struct intelxl_admin *admin ) {
200
-	size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
201
-	size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
202
 	const struct intelxl_admin_offsets *regs = admin->regs;
213
 	const struct intelxl_admin_offsets *regs = admin->regs;
203
 	void *admin_regs = ( intelxl->regs + admin->base );
214
 	void *admin_regs = ( intelxl->regs + admin->base );
204
 
215
 
205
 	/* Disable queue */
216
 	/* Disable queue */
206
 	writel ( 0, admin_regs + regs->len );
217
 	writel ( 0, admin_regs + regs->len );
218
+}
219
+
220
+/**
221
+ * Free admin queue
222
+ *
223
+ * @v intelxl		Intel device
224
+ * @v admin		Admin queue
225
+ */
226
+static void intelxl_free_admin ( struct intelxl_nic *intelxl __unused,
227
+				 struct intelxl_admin *admin ) {
228
+	size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
229
+	size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
207
 
230
 
208
 	/* Free queue */
231
 	/* Free queue */
209
 	free_dma ( admin->buf, ( buf_len + len ) );
232
 	free_dma ( admin->buf, ( buf_len + len ) );
705
  * @ret rc		Return status code
728
  * @ret rc		Return status code
706
  */
729
  */
707
 static int intelxl_open_admin ( struct intelxl_nic *intelxl ) {
730
 static int intelxl_open_admin ( struct intelxl_nic *intelxl ) {
708
-	unsigned int i;
709
 	int rc;
731
 	int rc;
710
 
732
 
711
-	/* Create admin event queue */
712
-	if ( ( rc = intelxl_create_admin ( intelxl, &intelxl->event ) ) != 0 )
713
-		goto err_create_event;
733
+	/* Allocate admin event queue */
734
+	if ( ( rc = intelxl_alloc_admin ( intelxl, &intelxl->event ) ) != 0 )
735
+		goto err_alloc_event;
714
 
736
 
715
-	/* Create admin command queue */
716
-	if ( ( rc = intelxl_create_admin ( intelxl, &intelxl->command ) ) != 0 )
717
-		goto err_create_command;
718
-
719
-	/* Initialise all admin event queue descriptors */
720
-	for ( i = 0 ; i < INTELXL_ADMIN_NUM_DESC ; i++ )
721
-		intelxl_admin_event_init ( intelxl, i );
737
+	/* Allocate admin command queue */
738
+	if ( ( rc = intelxl_alloc_admin ( intelxl, &intelxl->command ) ) != 0 )
739
+		goto err_alloc_command;
722
 
740
 
723
-	/* Post all descriptors to event queue */
724
-	intelxl_refill_admin ( intelxl );
741
+	/* (Re)open admin queues */
742
+	intelxl_reopen_admin ( intelxl );
725
 
743
 
726
 	/* Get firmware version */
744
 	/* Get firmware version */
727
 	if ( ( rc = intelxl_admin_version ( intelxl ) ) != 0 )
745
 	if ( ( rc = intelxl_admin_version ( intelxl ) ) != 0 )
735
 
753
 
736
  err_driver:
754
  err_driver:
737
  err_version:
755
  err_version:
738
-	intelxl_destroy_admin ( intelxl, &intelxl->command );
739
- err_create_command:
740
-	intelxl_destroy_admin ( intelxl, &intelxl->event );
741
- err_create_event:
756
+	intelxl_disable_admin ( intelxl, &intelxl->command );
757
+	intelxl_disable_admin ( intelxl, &intelxl->event );
758
+	intelxl_free_admin ( intelxl, &intelxl->command );
759
+ err_alloc_command:
760
+	intelxl_free_admin ( intelxl, &intelxl->event );
761
+ err_alloc_event:
742
 	return rc;
762
 	return rc;
743
 }
763
 }
744
 
764
 
765
+/**
766
+ * Reopen admin queues (after virtual function reset)
767
+ *
768
+ * @v intelxl		Intel device
769
+ */
770
+static void intelxl_reopen_admin ( struct intelxl_nic *intelxl ) {
771
+	unsigned int i;
772
+
773
+	/* Enable admin event queue */
774
+	intelxl_enable_admin ( intelxl, &intelxl->event );
775
+
776
+	/* Enable admin command queue */
777
+	intelxl_enable_admin ( intelxl, &intelxl->command );
778
+
779
+	/* Initialise all admin event queue descriptors */
780
+	for ( i = 0 ; i < INTELXL_ADMIN_NUM_DESC ; i++ )
781
+		intelxl_admin_event_init ( intelxl, i );
782
+
783
+	/* Post all descriptors to event queue */
784
+	intelxl_refill_admin ( intelxl );
785
+}
786
+
745
 /**
787
 /**
746
  * Close admin queues
788
  * Close admin queues
747
  *
789
  *
752
 	/* Shut down admin queues */
794
 	/* Shut down admin queues */
753
 	intelxl_admin_shutdown ( intelxl );
795
 	intelxl_admin_shutdown ( intelxl );
754
 
796
 
755
-	/* Destroy admin command queue */
756
-	intelxl_destroy_admin ( intelxl, &intelxl->command );
797
+	/* Disable admin queues */
798
+	intelxl_disable_admin ( intelxl, &intelxl->command );
799
+	intelxl_disable_admin ( intelxl, &intelxl->event );
757
 
800
 
758
-	/* Destroy admin event queue */
759
-	intelxl_destroy_admin ( intelxl, &intelxl->event );
801
+	/* Free admin queues */
802
+	intelxl_free_admin ( intelxl, &intelxl->command );
803
+	intelxl_free_admin ( intelxl, &intelxl->event );
760
 }
804
 }
761
 
805
 
762
 /******************************************************************************
806
 /******************************************************************************

Loading…
Cancel
Save