static void handle_request()

in core-cdev.c [666:750]


static void handle_request(struct fw_card *card, struct fw_request *request,
			   int tcode, int destination, int source,
			   int generation, unsigned long long offset,
			   void *payload, size_t length, void *callback_data)
{
	struct address_handler_resource *handler = callback_data;
	struct inbound_transaction_resource *r;
	struct inbound_transaction_event *e;
	size_t event_size0;
	void *fcp_frame = NULL;
	int ret;

	/* card may be different from handler->client->device->card */
	fw_card_get(card);

	r = kmalloc(sizeof(*r), GFP_ATOMIC);
	e = kmalloc(sizeof(*e), GFP_ATOMIC);
	if (r == NULL || e == NULL)
		goto failed;

	r->card    = card;
	r->request = request;
	r->data    = payload;
	r->length  = length;

	if (is_fcp_request(request)) {
		/*
		 * FIXME: Let core-transaction.c manage a
		 * single reference-counted copy?
		 */
		fcp_frame = kmemdup(payload, length, GFP_ATOMIC);
		if (fcp_frame == NULL)
			goto failed;

		r->data = fcp_frame;
	}

	r->resource.release = release_request;
	ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC);
	if (ret < 0)
		goto failed;

	if (handler->client->version < FW_CDEV_VERSION_EVENT_REQUEST2) {
		struct fw_cdev_event_request *req = &e->req.request;

		if (tcode & 0x10)
			tcode = TCODE_LOCK_REQUEST;

		req->type	= FW_CDEV_EVENT_REQUEST;
		req->tcode	= tcode;
		req->offset	= offset;
		req->length	= length;
		req->handle	= r->resource.handle;
		req->closure	= handler->closure;
		event_size0	= sizeof(*req);
	} else {
		struct fw_cdev_event_request2 *req = &e->req.request2;

		req->type	= FW_CDEV_EVENT_REQUEST2;
		req->tcode	= tcode;
		req->offset	= offset;
		req->source_node_id = source;
		req->destination_node_id = destination;
		req->card	= card->index;
		req->generation	= generation;
		req->length	= length;
		req->handle	= r->resource.handle;
		req->closure	= handler->closure;
		event_size0	= sizeof(*req);
	}

	queue_event(handler->client, &e->event,
		    &e->req, event_size0, r->data, length);
	return;

 failed:
	kfree(r);
	kfree(e);
	kfree(fcp_frame);

	if (!is_fcp_request(request))
		fw_send_response(card, request, RCODE_CONFLICT_ERROR);

	fw_card_put(card);
}