Преглед изворни кода

[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 година
родитељ
комит
7b68c310f9
1 измењених фајлова са 85 додато и 41 уклоњено
  1. 85
    41
      src/drivers/net/intelxl.c

+ 85
- 41
src/drivers/net/intelxl.c Прегледај датотеку

@@ -45,6 +45,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
45 45
  *
46 46
  */
47 47
 
48
+static void intelxl_reopen_admin ( struct intelxl_nic *intelxl );
49
+
48 50
 /******************************************************************************
49 51
  *
50 52
  * Device reset
@@ -133,19 +135,16 @@ static const struct intelxl_admin_offsets intelxl_admin_offsets = {
133 135
 };
134 136
 
135 137
 /**
136
- * Create admin queue
138
+ * Allocate admin queue
137 139
  *
138 140
  * @v intelxl		Intel device
139 141
  * @v admin		Admin queue
140 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 146
 	size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
145 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 149
 	/* Allocate admin queue */
151 150
 	admin->buf = malloc_dma ( ( buf_len + len ), INTELXL_ALIGN );
@@ -153,6 +152,30 @@ static int intelxl_create_admin ( struct intelxl_nic *intelxl,
153 152
 		return -ENOMEM;
154 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 179
 	/* Initialise admin queue */
157 180
 	memset ( admin->desc, 0, len );
158 181
 
@@ -177,33 +200,33 @@ static int intelxl_create_admin ( struct intelxl_nic *intelxl,
177 200
 	writel ( ( INTELXL_ADMIN_LEN_LEN ( INTELXL_ADMIN_NUM_DESC ) |
178 201
 		   INTELXL_ADMIN_LEN_ENABLE ),
179 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 208
  * @v intelxl		Intel device
196 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 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 213
 	const struct intelxl_admin_offsets *regs = admin->regs;
203 214
 	void *admin_regs = ( intelxl->regs + admin->base );
204 215
 
205 216
 	/* Disable queue */
206 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 231
 	/* Free queue */
209 232
 	free_dma ( admin->buf, ( buf_len + len ) );
@@ -705,23 +728,18 @@ static void intelxl_poll_admin ( struct net_device *netdev ) {
705 728
  * @ret rc		Return status code
706 729
  */
707 730
 static int intelxl_open_admin ( struct intelxl_nic *intelxl ) {
708
-	unsigned int i;
709 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 744
 	/* Get firmware version */
727 745
 	if ( ( rc = intelxl_admin_version ( intelxl ) ) != 0 )
@@ -735,13 +753,37 @@ static int intelxl_open_admin ( struct intelxl_nic *intelxl ) {
735 753
 
736 754
  err_driver:
737 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 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 788
  * Close admin queues
747 789
  *
@@ -752,11 +794,13 @@ static void intelxl_close_admin ( struct intelxl_nic *intelxl ) {
752 794
 	/* Shut down admin queues */
753 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…
Откажи
Сачувај