@@ -104,12 +104,144 @@ static int pvcalls_front_remove(struct xenbus_device *dev)
104
104
static int pvcalls_front_probe (struct xenbus_device * dev ,
105
105
const struct xenbus_device_id * id )
106
106
{
107
+ int ret = - ENOMEM , evtchn , i ;
108
+ unsigned int max_page_order , function_calls , len ;
109
+ char * versions ;
110
+ grant_ref_t gref_head = 0 ;
111
+ struct xenbus_transaction xbt ;
112
+ struct pvcalls_bedata * bedata = NULL ;
113
+ struct xen_pvcalls_sring * sring ;
114
+
115
+ if (pvcalls_front_dev != NULL ) {
116
+ dev_err (& dev -> dev , "only one PV Calls connection supported\n" );
117
+ return - EINVAL ;
118
+ }
119
+
120
+ versions = xenbus_read (XBT_NIL , dev -> otherend , "versions" , & len );
121
+ if (!len )
122
+ return - EINVAL ;
123
+ if (strcmp (versions , "1" )) {
124
+ kfree (versions );
125
+ return - EINVAL ;
126
+ }
127
+ kfree (versions );
128
+ max_page_order = xenbus_read_unsigned (dev -> otherend ,
129
+ "max-page-order" , 0 );
130
+ if (max_page_order < PVCALLS_RING_ORDER )
131
+ return - ENODEV ;
132
+ function_calls = xenbus_read_unsigned (dev -> otherend ,
133
+ "function-calls" , 0 );
134
+ /* See XENBUS_FUNCTIONS_CALLS in pvcalls.h */
135
+ if (function_calls != 1 )
136
+ return - ENODEV ;
137
+ pr_info ("%s max-page-order is %u\n" , __func__ , max_page_order );
138
+
139
+ bedata = kzalloc (sizeof (struct pvcalls_bedata ), GFP_KERNEL );
140
+ if (!bedata )
141
+ return - ENOMEM ;
142
+
143
+ dev_set_drvdata (& dev -> dev , bedata );
144
+ pvcalls_front_dev = dev ;
145
+ init_waitqueue_head (& bedata -> inflight_req );
146
+ INIT_LIST_HEAD (& bedata -> socket_mappings );
147
+ spin_lock_init (& bedata -> socket_lock );
148
+ bedata -> irq = -1 ;
149
+ bedata -> ref = -1 ;
150
+
151
+ for (i = 0 ; i < PVCALLS_NR_RSP_PER_RING ; i ++ )
152
+ bedata -> rsp [i ].req_id = PVCALLS_INVALID_ID ;
153
+
154
+ sring = (struct xen_pvcalls_sring * ) __get_free_page (GFP_KERNEL |
155
+ __GFP_ZERO );
156
+ if (!sring )
157
+ goto error ;
158
+ SHARED_RING_INIT (sring );
159
+ FRONT_RING_INIT (& bedata -> ring , sring , XEN_PAGE_SIZE );
160
+
161
+ ret = xenbus_alloc_evtchn (dev , & evtchn );
162
+ if (ret )
163
+ goto error ;
164
+
165
+ bedata -> irq = bind_evtchn_to_irqhandler (evtchn ,
166
+ pvcalls_front_event_handler ,
167
+ 0 , "pvcalls-frontend" , dev );
168
+ if (bedata -> irq < 0 ) {
169
+ ret = bedata -> irq ;
170
+ goto error ;
171
+ }
172
+
173
+ ret = gnttab_alloc_grant_references (1 , & gref_head );
174
+ if (ret < 0 )
175
+ goto error ;
176
+ bedata -> ref = gnttab_claim_grant_reference (& gref_head );
177
+ if (bedata -> ref < 0 ) {
178
+ ret = bedata -> ref ;
179
+ goto error ;
180
+ }
181
+ gnttab_grant_foreign_access_ref (bedata -> ref , dev -> otherend_id ,
182
+ virt_to_gfn ((void * )sring ), 0 );
183
+
184
+ again :
185
+ ret = xenbus_transaction_start (& xbt );
186
+ if (ret ) {
187
+ xenbus_dev_fatal (dev , ret , "starting transaction" );
188
+ goto error ;
189
+ }
190
+ ret = xenbus_printf (xbt , dev -> nodename , "version" , "%u" , 1 );
191
+ if (ret )
192
+ goto error_xenbus ;
193
+ ret = xenbus_printf (xbt , dev -> nodename , "ring-ref" , "%d" , bedata -> ref );
194
+ if (ret )
195
+ goto error_xenbus ;
196
+ ret = xenbus_printf (xbt , dev -> nodename , "port" , "%u" ,
197
+ evtchn );
198
+ if (ret )
199
+ goto error_xenbus ;
200
+ ret = xenbus_transaction_end (xbt , 0 );
201
+ if (ret ) {
202
+ if (ret == - EAGAIN )
203
+ goto again ;
204
+ xenbus_dev_fatal (dev , ret , "completing transaction" );
205
+ goto error ;
206
+ }
207
+ xenbus_switch_state (dev , XenbusStateInitialised );
208
+
107
209
return 0 ;
210
+
211
+ error_xenbus :
212
+ xenbus_transaction_end (xbt , 1 );
213
+ xenbus_dev_fatal (dev , ret , "writing xenstore" );
214
+ error :
215
+ pvcalls_front_remove (dev );
216
+ return ret ;
108
217
}
109
218
110
219
static void pvcalls_front_changed (struct xenbus_device * dev ,
111
220
enum xenbus_state backend_state )
112
221
{
222
+ switch (backend_state ) {
223
+ case XenbusStateReconfiguring :
224
+ case XenbusStateReconfigured :
225
+ case XenbusStateInitialising :
226
+ case XenbusStateInitialised :
227
+ case XenbusStateUnknown :
228
+ break ;
229
+
230
+ case XenbusStateInitWait :
231
+ break ;
232
+
233
+ case XenbusStateConnected :
234
+ xenbus_switch_state (dev , XenbusStateConnected );
235
+ break ;
236
+
237
+ case XenbusStateClosed :
238
+ if (dev -> state == XenbusStateClosed )
239
+ break ;
240
+ /* Missed the backend's CLOSING state -- fallthrough */
241
+ case XenbusStateClosing :
242
+ xenbus_frontend_closed (dev );
243
+ break ;
244
+ }
113
245
}
114
246
115
247
static struct xenbus_driver pvcalls_front_driver = {
0 commit comments