in sbp2.c [405:454]
static void sbp2_status_write(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 sbp2_logical_unit *lu = callback_data;
struct sbp2_orb *orb;
struct sbp2_status status;
unsigned long flags;
if (tcode != TCODE_WRITE_BLOCK_REQUEST ||
length < 8 || length > sizeof(status)) {
fw_send_response(card, request, RCODE_TYPE_ERROR);
return;
}
status.status = be32_to_cpup(payload);
status.orb_low = be32_to_cpup(payload + 4);
memset(status.data, 0, sizeof(status.data));
if (length > 8)
memcpy(status.data, payload + 8, length - 8);
if (STATUS_GET_SOURCE(status) == 2 || STATUS_GET_SOURCE(status) == 3) {
dev_notice(lu_dev(lu),
"non-ORB related status write, not handled\n");
fw_send_response(card, request, RCODE_COMPLETE);
return;
}
/* Lookup the orb corresponding to this status write. */
spin_lock_irqsave(&lu->tgt->lock, flags);
list_for_each_entry(orb, &lu->orb_list, link) {
if (STATUS_GET_ORB_HIGH(status) == 0 &&
STATUS_GET_ORB_LOW(status) == orb->request_bus) {
orb->rcode = RCODE_COMPLETE;
list_del(&orb->link);
break;
}
}
spin_unlock_irqrestore(&lu->tgt->lock, flags);
if (&orb->link != &lu->orb_list) {
orb->callback(orb, &status);
kref_put(&orb->kref, free_orb); /* orb callback reference */
} else {
dev_err(lu_dev(lu), "status write for unknown ORB\n");
}
fw_send_response(card, request, RCODE_COMPLETE);
}