Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2639a6fb authored by Kristian Høgsberg's avatar Kristian Høgsberg Committed by Stefan Richter
Browse files

firewire: Use struct fw_packet for incoming packets too in controller interface.

parent 748086eb
Loading
Loading
Loading
Loading
+41 −20
Original line number Diff line number Diff line
@@ -221,24 +221,48 @@ static void ar_context_tasklet(unsigned long data)
{
	struct ar_context *ctx = (struct ar_context *)data;
	struct fw_ohci *ohci = ctx->ohci;
	u32 status;
	int length, speed, ack, timestamp, tcode;
	struct fw_packet p;
	u32 status, length, tcode;

	/* FIXME: What to do about evt_* errors? */
	length    = le16_to_cpu(ctx->descriptor.req_count) -
		le16_to_cpu(ctx->descriptor.res_count) - 4;
	status    = le32_to_cpu(ctx->buffer[length / 4]);
	ack       = ((status >> 16) & 0x1f) - 16;
	speed     = (status >> 21) & 0x7;
	timestamp = status & 0xffff;

	ctx->buffer[0] = le32_to_cpu(ctx->buffer[0]);
	ctx->buffer[1] = le32_to_cpu(ctx->buffer[1]);
	ctx->buffer[2] = le32_to_cpu(ctx->buffer[2]);
	p.ack        = ((status >> 16) & 0x1f) - 16;
	p.speed      = (status >> 21) & 0x7;
	p.timestamp  = status & 0xffff;
	p.generation = ohci->request_generation;

	p.header[0] = le32_to_cpu(ctx->buffer[0]);
	p.header[1] = le32_to_cpu(ctx->buffer[1]);
	p.header[2] = le32_to_cpu(ctx->buffer[2]);

	tcode = (p.header[0] >> 4) & 0x0f;
	switch (tcode) {
	case TCODE_WRITE_QUADLET_REQUEST:
	case TCODE_READ_QUADLET_RESPONSE:
		p.header[3] = ctx->buffer[3];
		p.header_length = 16;
		break;

	tcode = (ctx->buffer[0] >> 4) & 0x0f;
	if (TCODE_IS_BLOCK_PACKET(tcode))
		ctx->buffer[3] = le32_to_cpu(ctx->buffer[3]);
	case TCODE_WRITE_BLOCK_REQUEST:
	case TCODE_READ_BLOCK_REQUEST :
	case TCODE_READ_BLOCK_RESPONSE:
	case TCODE_LOCK_REQUEST:
	case TCODE_LOCK_RESPONSE:
		p.header[3] = le32_to_cpu(ctx->buffer[3]);
		p.header_length = 16;
		break;

	case TCODE_WRITE_RESPONSE:
	case TCODE_READ_QUADLET_REQUEST:
		p.header_length = 12;
		break;
	}

	p.payload = (void *) ctx->buffer + p.header_length;
	p.payload_length = length - p.header_length;

	/* The OHCI bus reset handler synthesizes a phy packet with
	 * the new generation number when a bus reset happens (see
@@ -248,15 +272,12 @@ static void ar_context_tasklet(unsigned long data)
	 * we use the unique tlabel for finding the matching
	 * request. */

	if (ack + 16 == 0x09)
	if (p.ack + 16 == 0x09)
		ohci->request_generation = (ctx->buffer[2] >> 16) & 0xff;
	else if (ctx == &ohci->ar_request_ctx)
		fw_core_handle_request(&ohci->card, speed, ack, timestamp,
				       ohci->request_generation,
				       length, ctx->buffer);
		fw_core_handle_request(&ohci->card, &p);
	else
		fw_core_handle_response(&ohci->card, speed, ack, timestamp,
					length, ctx->buffer);
		fw_core_handle_response(&ohci->card, &p);

	ctx->descriptor.data_address = cpu_to_le32(ctx->buffer_bus);
	ctx->descriptor.req_count    = cpu_to_le16(sizeof ctx->buffer);
@@ -323,15 +344,15 @@ do_packet_callbacks(struct fw_ohci *ohci, struct list_head *list)
	struct fw_packet *p, *next;

	list_for_each_entry_safe(p, next, list, link)
		p->callback(p, &ohci->card, p->status);
		p->callback(p, &ohci->card, p->ack);
}

static void
complete_transmission(struct fw_packet *packet,
		      int status, struct list_head *list)
		      int ack, struct list_head *list)
{
	list_move_tail(&packet->link, list);
	packet->status = status;
	packet->ack = ack;
}

/* This function prepares the first packet in the context queue for
+47 −52
Original line number Diff line number Diff line
@@ -426,15 +426,15 @@ free_response_callback(struct fw_packet *packet,

static void
fw_fill_response(struct fw_packet *response,
		 u32 *request, u32 *data, size_t length)
		 struct fw_packet *request, void *data)
{
	int tcode, tlabel, extended_tcode, source, destination;

	tcode          = header_get_tcode(request[0]);
	tlabel         = header_get_tlabel(request[0]);
	source         = header_get_destination(request[0]);
	destination    = header_get_source(request[1]);
	extended_tcode = header_get_extended_tcode(request[3]);
	tcode          = header_get_tcode(request->header[0]);
	tlabel         = header_get_tlabel(request->header[0]);
	source         = header_get_destination(request->header[0]);
	destination    = header_get_source(request->header[1]);
	extended_tcode = header_get_extended_tcode(request->header[3]);

	response->header[0] =
		header_retry(RETRY_1) |
@@ -463,11 +463,11 @@ fw_fill_response(struct fw_packet *response,
	case TCODE_LOCK_REQUEST:
		response->header[0] |= header_tcode(tcode + 2);
		response->header[3] =
			header_data_length(length) |
			header_data_length(request->payload_length) |
			header_extended_tcode(extended_tcode);
		response->header_length = 16;
		response->payload = data;
		response->payload_length = length;
		response->payload_length = request->payload_length;
		break;

	default:
@@ -477,24 +477,23 @@ fw_fill_response(struct fw_packet *response,
}

static struct fw_request *
allocate_request(u32 *header, int ack,
		 int speed, int timestamp, int generation)
allocate_request(struct fw_packet *p)
{
	struct fw_request *request;
	u32 *data, length;
	int request_tcode;
	int request_tcode, t;

	request_tcode = header_get_tcode(header[0]);
	request_tcode = header_get_tcode(p->header[0]);
	switch (request_tcode) {
	case TCODE_WRITE_QUADLET_REQUEST:
		data = &header[3];
		data = &p->header[3];
		length = 4;
		break;

	case TCODE_WRITE_BLOCK_REQUEST:
	case TCODE_LOCK_REQUEST:
		data = &header[4];
		length = header_get_data_length(header[3]);
		data = p->payload;
		length = header_get_data_length(p->header[3]);
		break;

	case TCODE_READ_QUADLET_REQUEST:
@@ -504,7 +503,7 @@ allocate_request(u32 *header, int ack,

	case TCODE_READ_BLOCK_REQUEST:
		data = NULL;
		length = header_get_data_length(header[3]);
		length = header_get_data_length(p->header[3]);
		break;

	default:
@@ -516,16 +515,22 @@ allocate_request(u32 *header, int ack,
	if (request == NULL)
		return NULL;

	request->response.speed = speed;
	request->response.timestamp = timestamp;
	request->response.generation = generation;
	t = (p->timestamp & 0x1fff) + 4000;
	if (t >= 8000)
		t = (p->timestamp & ~0x1fff) + 0x2000 + t - 8000;
	else
		t = (p->timestamp & ~0x1fff) + t;

	request->response.speed = p->speed;
	request->response.timestamp = t;
	request->response.generation = p->generation;
	request->response.callback = free_response_callback;
	request->ack = ack;
	request->length = length;
	request->ack = p->ack;
	request->length = p->payload_length;
	if (data)
		memcpy(request->data, data, length);
		memcpy(request->data, p->payload, p->payload_length);

	fw_fill_response(&request->response, header, request->data, length);
	fw_fill_response(&request->response, p, request->data);

	return request;
}
@@ -554,31 +559,23 @@ fw_send_response(struct fw_card *card, struct fw_request *request, int rcode)
EXPORT_SYMBOL(fw_send_response);

void
fw_core_handle_request(struct fw_card *card,
		       int speed, int ack, int timestamp,
		       int generation, u32 length, u32 *header)
fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
{
	struct fw_address_handler *handler;
	struct fw_request *request;
	unsigned long long offset;
	unsigned long flags;
	int tcode, destination, source, t;
	int tcode, destination, source;

	if (length > 2048) {
	if (p->payload_length > 2048) {
		/* FIXME: send error response. */
		return;
	}

	if (ack != ACK_PENDING && ack != ACK_COMPLETE)
	if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE)
		return;

	t = (timestamp & 0x1fff) + 4000;
	if (t >= 8000)
		t = (timestamp & ~0x1fff) + 0x2000 + t - 8000;
	else
		t = (timestamp & ~0x1fff) + t;

	request = allocate_request(header, ack, speed, t, generation);
	request = allocate_request(p);
	if (request == NULL) {
		/* FIXME: send statically allocated busy packet. */
		return;
@@ -586,10 +583,10 @@ fw_core_handle_request(struct fw_card *card,

	offset      =
		((unsigned long long)
		 header_get_offset_high(header[1]) << 32) | header[2];
	tcode       = header_get_tcode(header[0]);
	destination = header_get_destination(header[0]);
	source      = header_get_source(header[0]);
		 header_get_offset_high(p->header[1]) << 32) | p->header[2];
	tcode       = header_get_tcode(p->header[0]);
	destination = header_get_destination(p->header[0]);
	source      = header_get_source(p->header[0]);

	spin_lock_irqsave(&address_handler_lock, flags);
	handler = lookup_enclosing_address_handler(&address_handler_list,
@@ -607,16 +604,14 @@ fw_core_handle_request(struct fw_card *card,
	else
		handler->address_callback(card, request,
					  tcode, destination, source,
					  generation, speed, offset,
					  p->generation, p->speed, offset,
					  request->data, request->length,
					  handler->callback_data);
}
EXPORT_SYMBOL(fw_core_handle_request);

void
fw_core_handle_response(struct fw_card *card,
			int speed, int ack, int timestamp,
			u32 length, u32 *header)
fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
{
	struct fw_transaction *t;
	unsigned long flags;
@@ -624,11 +619,11 @@ fw_core_handle_response(struct fw_card *card,
	size_t data_length;
	int tcode, tlabel, destination, source, rcode;

	tcode       = header_get_tcode(header[0]);
	tlabel      = header_get_tlabel(header[0]);
	destination = header_get_destination(header[0]);
	source      = header_get_source(header[1]);
	rcode       = header_get_rcode(header[1]);
	tcode       = header_get_tcode(p->header[0]);
	tlabel      = header_get_tlabel(p->header[0]);
	destination = header_get_destination(p->header[0]);
	source      = header_get_source(p->header[1]);
	rcode       = header_get_rcode(p->header[1]);

	spin_lock_irqsave(&card->lock, flags);
	list_for_each_entry(t, &card->transaction_list, link) {
@@ -650,7 +645,7 @@ fw_core_handle_response(struct fw_card *card,

	switch (tcode) {
	case TCODE_READ_QUADLET_RESPONSE:
		data = (u32 *) &header[3];
		data = (u32 *) &p->header[3];
		data_length = 4;
		break;

@@ -661,8 +656,8 @@ fw_core_handle_response(struct fw_card *card,

	case TCODE_READ_BLOCK_RESPONSE:
	case TCODE_LOCK_RESPONSE:
		data = &header[4];
		data_length = header_get_data_length(header[3]);
		data = &p->header[4];
		data_length = header_get_data_length(p->header[3]);
		break;

	default:
+4 −9
Original line number Diff line number Diff line
@@ -180,7 +180,7 @@ struct fw_packet {
	 * must never block.
	 */
	fw_packet_callback_t callback;
	int status;
	int ack;
	struct list_head link;
};

@@ -415,14 +415,9 @@ fw_core_handle_bus_reset(struct fw_card *card,
			 int node_id, int generation,
			 int self_id_count, u32 *self_ids);
void
fw_core_handle_request(struct fw_card *card,
		       int speed, int ack, int timestamp,
		       int generation,
		       u32 length, u32 *payload);
void
fw_core_handle_response(struct fw_card *card,
			int speed, int ack, int timestamp,
			u32 length, u32 *payload);
fw_core_handle_request(struct fw_card *card, struct fw_packet *request);

void
fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);

#endif /* __fw_transaction_h */