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

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

Signed-off-by: default avatarKristian Høgsberg <krh@redhat.com>
Signed-off-by: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
parent 748086eb
...@@ -221,24 +221,48 @@ static void ar_context_tasklet(unsigned long data) ...@@ -221,24 +221,48 @@ static void ar_context_tasklet(unsigned long data)
{ {
struct ar_context *ctx = (struct ar_context *)data; struct ar_context *ctx = (struct ar_context *)data;
struct fw_ohci *ohci = ctx->ohci; struct fw_ohci *ohci = ctx->ohci;
u32 status; struct fw_packet p;
int length, speed, ack, timestamp, tcode; u32 status, length, tcode;
/* FIXME: What to do about evt_* errors? */ /* FIXME: What to do about evt_* errors? */
length = le16_to_cpu(ctx->descriptor.req_count) - length = le16_to_cpu(ctx->descriptor.req_count) -
le16_to_cpu(ctx->descriptor.res_count) - 4; le16_to_cpu(ctx->descriptor.res_count) - 4;
status = le32_to_cpu(ctx->buffer[length / 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]); p.ack = ((status >> 16) & 0x1f) - 16;
ctx->buffer[1] = le32_to_cpu(ctx->buffer[1]); p.speed = (status >> 21) & 0x7;
ctx->buffer[2] = le32_to_cpu(ctx->buffer[2]); 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;
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;
}
tcode = (ctx->buffer[0] >> 4) & 0x0f; p.payload = (void *) ctx->buffer + p.header_length;
if (TCODE_IS_BLOCK_PACKET(tcode)) p.payload_length = length - p.header_length;
ctx->buffer[3] = le32_to_cpu(ctx->buffer[3]);
/* The OHCI bus reset handler synthesizes a phy packet with /* The OHCI bus reset handler synthesizes a phy packet with
* the new generation number when a bus reset happens (see * the new generation number when a bus reset happens (see
...@@ -248,15 +272,12 @@ static void ar_context_tasklet(unsigned long data) ...@@ -248,15 +272,12 @@ static void ar_context_tasklet(unsigned long data)
* we use the unique tlabel for finding the matching * we use the unique tlabel for finding the matching
* request. */ * request. */
if (ack + 16 == 0x09) if (p.ack + 16 == 0x09)
ohci->request_generation = (ctx->buffer[2] >> 16) & 0xff; ohci->request_generation = (ctx->buffer[2] >> 16) & 0xff;
else if (ctx == &ohci->ar_request_ctx) else if (ctx == &ohci->ar_request_ctx)
fw_core_handle_request(&ohci->card, speed, ack, timestamp, fw_core_handle_request(&ohci->card, &p);
ohci->request_generation,
length, ctx->buffer);
else else
fw_core_handle_response(&ohci->card, speed, ack, timestamp, fw_core_handle_response(&ohci->card, &p);
length, ctx->buffer);
ctx->descriptor.data_address = cpu_to_le32(ctx->buffer_bus); ctx->descriptor.data_address = cpu_to_le32(ctx->buffer_bus);
ctx->descriptor.req_count = cpu_to_le16(sizeof ctx->buffer); 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) ...@@ -323,15 +344,15 @@ do_packet_callbacks(struct fw_ohci *ohci, struct list_head *list)
struct fw_packet *p, *next; struct fw_packet *p, *next;
list_for_each_entry_safe(p, next, list, link) 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 static void
complete_transmission(struct fw_packet *packet, complete_transmission(struct fw_packet *packet,
int status, struct list_head *list) int ack, struct list_head *list)
{ {
list_move_tail(&packet->link, list); list_move_tail(&packet->link, list);
packet->status = status; packet->ack = ack;
} }
/* This function prepares the first packet in the context queue for /* This function prepares the first packet in the context queue for
......
...@@ -426,15 +426,15 @@ free_response_callback(struct fw_packet *packet, ...@@ -426,15 +426,15 @@ free_response_callback(struct fw_packet *packet,
static void static void
fw_fill_response(struct fw_packet *response, 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; int tcode, tlabel, extended_tcode, source, destination;
tcode = header_get_tcode(request[0]); tcode = header_get_tcode(request->header[0]);
tlabel = header_get_tlabel(request[0]); tlabel = header_get_tlabel(request->header[0]);
source = header_get_destination(request[0]); source = header_get_destination(request->header[0]);
destination = header_get_source(request[1]); destination = header_get_source(request->header[1]);
extended_tcode = header_get_extended_tcode(request[3]); extended_tcode = header_get_extended_tcode(request->header[3]);
response->header[0] = response->header[0] =
header_retry(RETRY_1) | header_retry(RETRY_1) |
...@@ -463,11 +463,11 @@ fw_fill_response(struct fw_packet *response, ...@@ -463,11 +463,11 @@ fw_fill_response(struct fw_packet *response,
case TCODE_LOCK_REQUEST: case TCODE_LOCK_REQUEST:
response->header[0] |= header_tcode(tcode + 2); response->header[0] |= header_tcode(tcode + 2);
response->header[3] = response->header[3] =
header_data_length(length) | header_data_length(request->payload_length) |
header_extended_tcode(extended_tcode); header_extended_tcode(extended_tcode);
response->header_length = 16; response->header_length = 16;
response->payload = data; response->payload = data;
response->payload_length = length; response->payload_length = request->payload_length;
break; break;
default: default:
...@@ -477,24 +477,23 @@ fw_fill_response(struct fw_packet *response, ...@@ -477,24 +477,23 @@ fw_fill_response(struct fw_packet *response,
} }
static struct fw_request * static struct fw_request *
allocate_request(u32 *header, int ack, allocate_request(struct fw_packet *p)
int speed, int timestamp, int generation)
{ {
struct fw_request *request; struct fw_request *request;
u32 *data, length; 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) { switch (request_tcode) {
case TCODE_WRITE_QUADLET_REQUEST: case TCODE_WRITE_QUADLET_REQUEST:
data = &header[3]; data = &p->header[3];
length = 4; length = 4;
break; break;
case TCODE_WRITE_BLOCK_REQUEST: case TCODE_WRITE_BLOCK_REQUEST:
case TCODE_LOCK_REQUEST: case TCODE_LOCK_REQUEST:
data = &header[4]; data = p->payload;
length = header_get_data_length(header[3]); length = header_get_data_length(p->header[3]);
break; break;
case TCODE_READ_QUADLET_REQUEST: case TCODE_READ_QUADLET_REQUEST:
...@@ -504,7 +503,7 @@ allocate_request(u32 *header, int ack, ...@@ -504,7 +503,7 @@ allocate_request(u32 *header, int ack,
case TCODE_READ_BLOCK_REQUEST: case TCODE_READ_BLOCK_REQUEST:
data = NULL; data = NULL;
length = header_get_data_length(header[3]); length = header_get_data_length(p->header[3]);
break; break;
default: default:
...@@ -516,16 +515,22 @@ allocate_request(u32 *header, int ack, ...@@ -516,16 +515,22 @@ allocate_request(u32 *header, int ack,
if (request == NULL) if (request == NULL)
return NULL; return NULL;
request->response.speed = speed; t = (p->timestamp & 0x1fff) + 4000;
request->response.timestamp = timestamp; if (t >= 8000)
request->response.generation = generation; 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->response.callback = free_response_callback;
request->ack = ack; request->ack = p->ack;
request->length = length; request->length = p->payload_length;
if (data) 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; return request;
} }
...@@ -554,31 +559,23 @@ fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) ...@@ -554,31 +559,23 @@ fw_send_response(struct fw_card *card, struct fw_request *request, int rcode)
EXPORT_SYMBOL(fw_send_response); EXPORT_SYMBOL(fw_send_response);
void void
fw_core_handle_request(struct fw_card *card, fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
int speed, int ack, int timestamp,
int generation, u32 length, u32 *header)
{ {
struct fw_address_handler *handler; struct fw_address_handler *handler;
struct fw_request *request; struct fw_request *request;
unsigned long long offset; unsigned long long offset;
unsigned long flags; unsigned long flags;
int tcode, destination, source, t; int tcode, destination, source;
if (length > 2048) { if (p->payload_length > 2048) {
/* FIXME: send error response. */ /* FIXME: send error response. */
return; return;
} }
if (ack != ACK_PENDING && ack != ACK_COMPLETE) if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE)
return; return;
t = (timestamp & 0x1fff) + 4000; request = allocate_request(p);
if (t >= 8000)
t = (timestamp & ~0x1fff) + 0x2000 + t - 8000;
else
t = (timestamp & ~0x1fff) + t;
request = allocate_request(header, ack, speed, t, generation);
if (request == NULL) { if (request == NULL) {
/* FIXME: send statically allocated busy packet. */ /* FIXME: send statically allocated busy packet. */
return; return;
...@@ -586,10 +583,10 @@ fw_core_handle_request(struct fw_card *card, ...@@ -586,10 +583,10 @@ fw_core_handle_request(struct fw_card *card,
offset = offset =
((unsigned long long) ((unsigned long long)
header_get_offset_high(header[1]) << 32) | header[2]; header_get_offset_high(p->header[1]) << 32) | p->header[2];
tcode = header_get_tcode(header[0]); tcode = header_get_tcode(p->header[0]);
destination = header_get_destination(header[0]); destination = header_get_destination(p->header[0]);
source = header_get_source(header[0]); source = header_get_source(p->header[0]);
spin_lock_irqsave(&address_handler_lock, flags); spin_lock_irqsave(&address_handler_lock, flags);
handler = lookup_enclosing_address_handler(&address_handler_list, handler = lookup_enclosing_address_handler(&address_handler_list,
...@@ -607,16 +604,14 @@ fw_core_handle_request(struct fw_card *card, ...@@ -607,16 +604,14 @@ fw_core_handle_request(struct fw_card *card,
else else
handler->address_callback(card, request, handler->address_callback(card, request,
tcode, destination, source, tcode, destination, source,
generation, speed, offset, p->generation, p->speed, offset,
request->data, request->length, request->data, request->length,
handler->callback_data); handler->callback_data);
} }
EXPORT_SYMBOL(fw_core_handle_request); EXPORT_SYMBOL(fw_core_handle_request);
void void
fw_core_handle_response(struct fw_card *card, fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
int speed, int ack, int timestamp,
u32 length, u32 *header)
{ {
struct fw_transaction *t; struct fw_transaction *t;
unsigned long flags; unsigned long flags;
...@@ -624,11 +619,11 @@ fw_core_handle_response(struct fw_card *card, ...@@ -624,11 +619,11 @@ fw_core_handle_response(struct fw_card *card,
size_t data_length; size_t data_length;
int tcode, tlabel, destination, source, rcode; int tcode, tlabel, destination, source, rcode;
tcode = header_get_tcode(header[0]); tcode = header_get_tcode(p->header[0]);
tlabel = header_get_tlabel(header[0]); tlabel = header_get_tlabel(p->header[0]);
destination = header_get_destination(header[0]); destination = header_get_destination(p->header[0]);
source = header_get_source(header[1]); source = header_get_source(p->header[1]);
rcode = header_get_rcode(header[1]); rcode = header_get_rcode(p->header[1]);
spin_lock_irqsave(&card->lock, flags); spin_lock_irqsave(&card->lock, flags);
list_for_each_entry(t, &card->transaction_list, link) { list_for_each_entry(t, &card->transaction_list, link) {
...@@ -650,7 +645,7 @@ fw_core_handle_response(struct fw_card *card, ...@@ -650,7 +645,7 @@ fw_core_handle_response(struct fw_card *card,
switch (tcode) { switch (tcode) {
case TCODE_READ_QUADLET_RESPONSE: case TCODE_READ_QUADLET_RESPONSE:
data = (u32 *) &header[3]; data = (u32 *) &p->header[3];
data_length = 4; data_length = 4;
break; break;
...@@ -661,8 +656,8 @@ fw_core_handle_response(struct fw_card *card, ...@@ -661,8 +656,8 @@ fw_core_handle_response(struct fw_card *card,
case TCODE_READ_BLOCK_RESPONSE: case TCODE_READ_BLOCK_RESPONSE:
case TCODE_LOCK_RESPONSE: case TCODE_LOCK_RESPONSE:
data = &header[4]; data = &p->header[4];
data_length = header_get_data_length(header[3]); data_length = header_get_data_length(p->header[3]);
break; break;
default: default:
......
...@@ -180,7 +180,7 @@ struct fw_packet { ...@@ -180,7 +180,7 @@ struct fw_packet {
* must never block. * must never block.
*/ */
fw_packet_callback_t callback; fw_packet_callback_t callback;
int status; int ack;
struct list_head link; struct list_head link;
}; };
...@@ -415,14 +415,9 @@ fw_core_handle_bus_reset(struct fw_card *card, ...@@ -415,14 +415,9 @@ fw_core_handle_bus_reset(struct fw_card *card,
int node_id, int generation, int node_id, int generation,
int self_id_count, u32 *self_ids); int self_id_count, u32 *self_ids);
void void
fw_core_handle_request(struct fw_card *card, fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
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);
void
fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
#endif /* __fw_transaction_h */ #endif /* __fw_transaction_h */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment