static int asd_get_tmf_resp_tasklet(struct asd_ascb *ascb, struct done_list_struct *dl) { struct asd_ha_struct *asd_ha = ascb->ha; unsigned long flags; struct tc_resp_sb_struct { __le16 index_escb; u8 len_lsb; u8 flags; } __attribute__ ((packed)) *resp_sb = (void *) dl->status_block; int edb_id = ((resp_sb->flags & 0x70) >> 4)-1; struct asd_ascb *escb; struct asd_dma_tok *edb; struct ssp_frame_hdr *fh; struct ssp_response_iu *ru; int res = TMF_RESP_FUNC_FAILED; ASD_DPRINTK("tmf resp tasklet\n"); spin_lock_irqsave(&asd_ha->seq.tc_index_lock, flags); escb = asd_tc_index_find(&asd_ha->seq, (int)le16_to_cpu(resp_sb->index_escb)); spin_unlock_irqrestore(&asd_ha->seq.tc_index_lock, flags); if (!escb) { ASD_DPRINTK("Uh-oh! No escb for this dl?!\n"); return res; } edb = asd_ha->seq.edb_arr[edb_id + escb->edb_index]; ascb->tag = *(__be16 *)(edb->vaddr+4); fh = edb->vaddr + 16; ru = edb->vaddr + 16 + sizeof(*fh); res = ru->status; if (ru->datapres == 1) /* Response data present */ res = ru->resp_data[3]; #if 0 ascb->tag = fh->tag; #endif ascb->tag_valid = 1; asd_invalidate_edb(escb, edb_id); return res; }
static void asd_get_response_tasklet(struct asd_ascb *ascb, struct done_list_struct *dl) { struct asd_ha_struct *asd_ha = ascb->ha; struct sas_task *task = ascb->uldd_task; struct task_status_struct *ts = &task->task_status; unsigned long flags; struct tc_resp_sb_struct { __le16 index_escb; u8 len_lsb; u8 flags; } __attribute__ ((packed)) *resp_sb = (void *) dl->status_block; /* int size = ((resp_sb->flags & 7) << 8) | resp_sb->len_lsb; */ int edb_id = ((resp_sb->flags & 0x70) >> 4)-1; struct asd_ascb *escb; struct asd_dma_tok *edb; void *r; spin_lock_irqsave(&asd_ha->seq.tc_index_lock, flags); escb = asd_tc_index_find(&asd_ha->seq, (int)le16_to_cpu(resp_sb->index_escb)); spin_unlock_irqrestore(&asd_ha->seq.tc_index_lock, flags); if (!escb) { ASD_DPRINTK("Uh-oh! No escb for this dl?!\n"); return; } ts->buf_valid_size = 0; edb = asd_ha->seq.edb_arr[edb_id + escb->edb_index]; r = edb->vaddr; if (task->task_proto == SAS_PROTO_SSP) { struct ssp_response_iu *iu = r + 16 + sizeof(struct ssp_frame_hdr); ts->residual = le32_to_cpu(*(__le32 *)r); ts->resp = SAS_TASK_COMPLETE; if (iu->datapres == 0) ts->stat = iu->status; else if (iu->datapres == 1) ts->stat = iu->resp_data[3]; else if (iu->datapres == 2) { ts->stat = SAM_CHECK_COND; ts->buf_valid_size = min((u32) SAS_STATUS_BUF_SIZE, be32_to_cpu(iu->sense_data_len)); memcpy(ts->buf, iu->sense_data, ts->buf_valid_size); if (iu->status != SAM_CHECK_COND) { ASD_DPRINTK("device %llx sent sense data, but " "stat(0x%x) is not CHECK_CONDITION" "\n", SAS_ADDR(task->dev->sas_addr), ts->stat); } } } else { struct ata_task_resp *resp = (void *) &ts->buf[0]; ts->residual = le32_to_cpu(*(__le32 *)r); if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) { resp->frame_len = le16_to_cpu(*(__le16 *)(r+6)); memcpy(&resp->ending_fis[0], r+16, 24); ts->buf_valid_size = sizeof(*resp); } } asd_invalidate_edb(escb, edb_id); }