|
@@ -49,8 +49,133 @@ struct pvcalls_fedata {
|
|
struct semaphore socket_lock;
|
|
struct semaphore socket_lock;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static int pvcalls_back_socket(struct xenbus_device *dev,
|
|
|
|
+ struct xen_pvcalls_request *req)
|
|
|
|
+{
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int pvcalls_back_connect(struct xenbus_device *dev,
|
|
|
|
+ struct xen_pvcalls_request *req)
|
|
|
|
+{
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int pvcalls_back_release(struct xenbus_device *dev,
|
|
|
|
+ struct xen_pvcalls_request *req)
|
|
|
|
+{
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int pvcalls_back_bind(struct xenbus_device *dev,
|
|
|
|
+ struct xen_pvcalls_request *req)
|
|
|
|
+{
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int pvcalls_back_listen(struct xenbus_device *dev,
|
|
|
|
+ struct xen_pvcalls_request *req)
|
|
|
|
+{
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int pvcalls_back_accept(struct xenbus_device *dev,
|
|
|
|
+ struct xen_pvcalls_request *req)
|
|
|
|
+{
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int pvcalls_back_poll(struct xenbus_device *dev,
|
|
|
|
+ struct xen_pvcalls_request *req)
|
|
|
|
+{
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int pvcalls_back_handle_cmd(struct xenbus_device *dev,
|
|
|
|
+ struct xen_pvcalls_request *req)
|
|
|
|
+{
|
|
|
|
+ int ret = 0;
|
|
|
|
+
|
|
|
|
+ switch (req->cmd) {
|
|
|
|
+ case PVCALLS_SOCKET:
|
|
|
|
+ ret = pvcalls_back_socket(dev, req);
|
|
|
|
+ break;
|
|
|
|
+ case PVCALLS_CONNECT:
|
|
|
|
+ ret = pvcalls_back_connect(dev, req);
|
|
|
|
+ break;
|
|
|
|
+ case PVCALLS_RELEASE:
|
|
|
|
+ ret = pvcalls_back_release(dev, req);
|
|
|
|
+ break;
|
|
|
|
+ case PVCALLS_BIND:
|
|
|
|
+ ret = pvcalls_back_bind(dev, req);
|
|
|
|
+ break;
|
|
|
|
+ case PVCALLS_LISTEN:
|
|
|
|
+ ret = pvcalls_back_listen(dev, req);
|
|
|
|
+ break;
|
|
|
|
+ case PVCALLS_ACCEPT:
|
|
|
|
+ ret = pvcalls_back_accept(dev, req);
|
|
|
|
+ break;
|
|
|
|
+ case PVCALLS_POLL:
|
|
|
|
+ ret = pvcalls_back_poll(dev, req);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ {
|
|
|
|
+ struct pvcalls_fedata *fedata;
|
|
|
|
+ struct xen_pvcalls_response *rsp;
|
|
|
|
+
|
|
|
|
+ fedata = dev_get_drvdata(&dev->dev);
|
|
|
|
+ rsp = RING_GET_RESPONSE(
|
|
|
|
+ &fedata->ring, fedata->ring.rsp_prod_pvt++);
|
|
|
|
+ rsp->req_id = req->req_id;
|
|
|
|
+ rsp->cmd = req->cmd;
|
|
|
|
+ rsp->ret = -ENOTSUPP;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void pvcalls_back_work(struct pvcalls_fedata *fedata)
|
|
|
|
+{
|
|
|
|
+ int notify, notify_all = 0, more = 1;
|
|
|
|
+ struct xen_pvcalls_request req;
|
|
|
|
+ struct xenbus_device *dev = fedata->dev;
|
|
|
|
+
|
|
|
|
+ while (more) {
|
|
|
|
+ while (RING_HAS_UNCONSUMED_REQUESTS(&fedata->ring)) {
|
|
|
|
+ RING_COPY_REQUEST(&fedata->ring,
|
|
|
|
+ fedata->ring.req_cons++,
|
|
|
|
+ &req);
|
|
|
|
+
|
|
|
|
+ if (!pvcalls_back_handle_cmd(dev, &req)) {
|
|
|
|
+ RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(
|
|
|
|
+ &fedata->ring, notify);
|
|
|
|
+ notify_all += notify;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (notify_all) {
|
|
|
|
+ notify_remote_via_irq(fedata->irq);
|
|
|
|
+ notify_all = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ RING_FINAL_CHECK_FOR_REQUESTS(&fedata->ring, more);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static irqreturn_t pvcalls_back_event(int irq, void *dev_id)
|
|
static irqreturn_t pvcalls_back_event(int irq, void *dev_id)
|
|
{
|
|
{
|
|
|
|
+ struct xenbus_device *dev = dev_id;
|
|
|
|
+ struct pvcalls_fedata *fedata = NULL;
|
|
|
|
+
|
|
|
|
+ if (dev == NULL)
|
|
|
|
+ return IRQ_HANDLED;
|
|
|
|
+
|
|
|
|
+ fedata = dev_get_drvdata(&dev->dev);
|
|
|
|
+ if (fedata == NULL)
|
|
|
|
+ return IRQ_HANDLED;
|
|
|
|
+
|
|
|
|
+ pvcalls_back_work(fedata);
|
|
return IRQ_HANDLED;
|
|
return IRQ_HANDLED;
|
|
}
|
|
}
|
|
|
|
|