On Fri, Jan 27, 2017 at 11:28:45AM -0800, Raghava Aditya Renukunta wrote: > Added support to send out task management commands. > > Signed-off-by: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@xxxxxxxxxxxxx> > Signed-off-by: Dave Carroll <David.Carroll@xxxxxxxxxxxxx> > > --- [...] > @@ -3365,7 +3462,151 @@ static void aac_srb_callback(void *context, struct fib * fibptr) > > /** > * > - * aac_send_scb_fib > + * aac_hba_callback > + * @context: the context set in the fib - here it is scsi cmd > + * @fibptr: pointer to the fib > + * > + * Handles the completion of a native HBA scsi command > + * > + */ > +void aac_hba_callback(void *context, struct fib *fibptr) > +{ > + struct aac_dev *dev; > + struct scsi_cmnd *scsicmd; > + > + scsicmd = (struct scsi_cmnd *) context; > + > + if (!aac_valid_context(scsicmd, fibptr)) > + return; > + > + WARN_ON(fibptr == NULL); > + dev = fibptr->dev; > + > + if (!(fibptr->flags & FIB_CONTEXT_FLAG_NATIVE_HBA_TMF)) > + scsi_dma_unmap(scsicmd); > + > + if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) { > + /* fast response */ > + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; > + } else { > + struct aac_hba_resp *err = > + &((struct aac_native_hba *)fibptr->hw_fib_va)->resp.err; > + > + // BUG_ON(err->iu_type != HBA_IU_TYPE_RESP); Please zap that C++ comment and see if you can tidy up the remaining code a bit (e.g a new function for the else block, switch statement iterating over err->serivce_response, etc...) > + if (err->service_response == HBA_RESP_SVCRES_TASK_COMPLETE) { > + scsicmd->result = err->status; > + /* set residual count */ > + scsi_set_resid(scsicmd, > + le32_to_cpu(err->residual_count)); > + > + switch (err->status) { > + case SAM_STAT_GOOD: > + scsicmd->result |= DID_OK << 16 | > + COMMAND_COMPLETE << 8; > + break; > + case SAM_STAT_CHECK_CONDITION: > + { > + int len; > + > + len = min_t(u8, err->sense_response_data_len, > + SCSI_SENSE_BUFFERSIZE); > + if (len) > + memcpy(scsicmd->sense_buffer, > + err->sense_response_buf, len); > + scsicmd->result |= DID_OK << 16 | > + COMMAND_COMPLETE << 8; > + break; > + } > + case SAM_STAT_BUSY: > + scsicmd->result |= DID_BUS_BUSY << 16 | > + COMMAND_COMPLETE << 8; > + break; > + case SAM_STAT_TASK_ABORTED: > + scsicmd->result |= DID_ABORT << 16 | > + ABORT << 8; > + break; > + case SAM_STAT_RESERVATION_CONFLICT: > + case SAM_STAT_TASK_SET_FULL: > + default: > + scsicmd->result |= DID_ERROR << 16 | > + COMMAND_COMPLETE << 8; > + break; > + } > + } else if (err->service_response == HBA_RESP_SVCRES_FAILURE) { > + switch (err->status) { > + case HBA_RESP_STAT_HBAMODE_DISABLED: > + { > + u32 bus, cid; > + > + bus = aac_logical_to_phys( > + scmd_channel(scsicmd)); > + cid = scmd_id(scsicmd); > + if (dev->hba_map[bus][cid].devtype == > + AAC_DEVTYPE_NATIVE_RAW) { > + dev->hba_map[bus][cid].devtype = > + AAC_DEVTYPE_ARC_RAW; > + dev->hba_map[bus][cid].rmw_nexus = > + 0xffffffff; > + } > + scsicmd->result = DID_NO_CONNECT << 16 | > + COMMAND_COMPLETE << 8; > + break; > + } > + case HBA_RESP_STAT_IO_ERROR: > + case HBA_RESP_STAT_NO_PATH_TO_DEVICE: > + scsicmd->result = DID_OK << 16 | > + COMMAND_COMPLETE << 8 | SAM_STAT_BUSY; > + break; > + case HBA_RESP_STAT_IO_ABORTED: > + scsicmd->result = DID_ABORT << 16 | > + ABORT << 8; > + break; > + case HBA_RESP_STAT_INVALID_DEVICE: > + scsicmd->result = DID_NO_CONNECT << 16 | > + COMMAND_COMPLETE << 8; > + break; > + case HBA_RESP_STAT_UNDERRUN: > + /* UNDERRUN is OK */ > + scsicmd->result = DID_OK << 16 | > + COMMAND_COMPLETE << 8; > + break; > + case HBA_RESP_STAT_OVERRUN: > + default: > + scsicmd->result = DID_ERROR << 16 | > + COMMAND_COMPLETE << 8; > + break; > + } > + } else if (err->service_response == > + HBA_RESP_SVCRES_TMF_REJECTED) { > + scsicmd->result = > + DID_ERROR << 16 | MESSAGE_REJECT << 8; > + } else if (err->service_response == > + HBA_RESP_SVCRES_TMF_LUN_INVALID) { > + scsicmd->result = > + DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; > + } else if ((err->service_response == > + HBA_RESP_SVCRES_TMF_COMPLETE) || > + (err->service_response == > + HBA_RESP_SVCRES_TMF_SUCCEEDED)) { > + scsicmd->result = > + DID_OK << 16 | COMMAND_COMPLETE << 8; > + } else { > + scsicmd->result = > + DID_ERROR << 16 | COMMAND_COMPLETE << 8; > + } > + } > + > + aac_fib_complete(fibptr); > + > + if (fibptr->flags & FIB_CONTEXT_FLAG_NATIVE_HBA_TMF) > + scsicmd->SCp.sent_command = 1; > + else > + scsicmd->scsi_done(scsicmd); > +} [...] > @@ -3408,6 +3649,54 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) > return -1; > } > > +/** > + * > + * aac_send_hba_fib > + * @scsicmd: the scsi command block > + * > + * This routine will form a FIB and fill in the aac_hba_cmd_req from the > + * scsicmd passed in. > + */ > +static int aac_send_hba_fib(struct scsi_cmnd *scsicmd) > +{ > + struct fib *cmd_fibcontext; > + struct aac_dev *dev; > + int status; > + > + dev = (struct aac_dev *)scsicmd->device->host->hostdata; dev = shost_priv(scsicmd->device->host); [...] > @@ -3660,6 +3949,73 @@ static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int > return 0; > } > > +static long aac_build_sghba(struct scsi_cmnd *scsicmd, > + struct aac_hba_cmd_req *hbacmd, > + int sg_max, > + u64 sg_address) > +{ > + unsigned long byte_count = 0; > + int nseg; > + > + nseg = scsi_dma_map(scsicmd); > + if (nseg < 0) > + return nseg; if (nseg <= 0) return nseg; > + if (nseg) { > + struct scatterlist *sg; > + int i; > + u32 cur_size; > + struct aac_hba_sgl *sge; > + > + if (nseg > HBA_MAX_SG_EMBEDDED) > + sge = &hbacmd->sge[2]; > + else > + sge = &hbacmd->sge[0]; > + > + scsi_for_each_sg(scsicmd, sg, nseg, i) { > + int count = sg_dma_len(sg); > + u64 addr = sg_dma_address(sg); > + > + WARN_ON(i >= sg_max); > + sge->addr_hi = cpu_to_le32((u32)(addr>>32)); > + sge->addr_lo = cpu_to_le32((u32)(addr & 0xffffffff)); > + cur_size = cpu_to_le32(count); > + sge->len = cur_size; > + sge->flags = 0; > + byte_count += count; > + sge++; > + } > + > + sge--; > + /* hba wants the size to be exact */ > + if (byte_count > scsi_bufflen(scsicmd)) { > + u32 temp = le32_to_cpu(sge->len) - > + (byte_count - scsi_bufflen(scsicmd)); > + sge->len = cpu_to_le32(temp); > + byte_count = scsi_bufflen(scsicmd); > + } > + > + if (nseg <= HBA_MAX_SG_EMBEDDED) { > + hbacmd->emb_data_desc_count = cpu_to_le32(nseg); > + sge->flags = cpu_to_le32(0x40000000); > + } else { > + /* not embedded */ > + hbacmd->sge[0].flags = cpu_to_le32(0x80000000); > + hbacmd->emb_data_desc_count = (u8)cpu_to_le32(1); > + hbacmd->sge[0].addr_hi = > + (u32)cpu_to_le32(sg_address >> 32); > + hbacmd->sge[0].addr_lo = > + cpu_to_le32((u32)(sg_address & 0xffffffff)); > + } > + > + /* Check for command underflow */ > + if (scsicmd->underflow && (byte_count < scsicmd->underflow)) { > + pr_warn("aacraid: cmd len %08lX cmd underflow %08X\n", > + byte_count, scsicmd->underflow); > + } > + } > + return byte_count; > +} > + > #ifdef AAC_DETAILED_STATUS_INFO > > struct aac_srb_status_info { > -- > 2.7.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Johannes Thumshirn Storage jthumshirn@xxxxxxx +49 911 74053 689 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: Felix Imendörffer, Jane Smithard, Graham Norton HRB 21284 (AG Nürnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html