Fix FC target mode in mpt(4), broken in multiple ways.
- Not set BufferLength caused receive of empty ATIOs. - CDB length guessing was broken at least for RC16. - mpt_req_untimeout() was called with wrong req parameter. - Sense data reporting was broken in several ways. With this change my LSI7204EP-LC can pass at least basic tests as target. The code is still far from perfect, but finally I found second hw/driver after isp(4) that really can work in CAM target mode. MFC after: 2 weeks
This commit is contained in:
parent
1b835e81ca
commit
93612a52c7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=314998
@ -949,24 +949,6 @@ void mpt_prtc(struct mpt_softc *, const char *, ...)
|
||||
__printflike(2, 3);
|
||||
|
||||
/**************************** Target Mode Related ***************************/
|
||||
static __inline int mpt_cdblen(uint8_t, int);
|
||||
static __inline int
|
||||
mpt_cdblen(uint8_t cdb0, int maxlen)
|
||||
{
|
||||
int group = cdb0 >> 5;
|
||||
switch (group) {
|
||||
case 0:
|
||||
return (6);
|
||||
case 1:
|
||||
return (10);
|
||||
case 4:
|
||||
case 5:
|
||||
return (12);
|
||||
default:
|
||||
return (16);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INVARIANTS
|
||||
static __inline request_t * mpt_tag_2_req(struct mpt_softc *, uint32_t);
|
||||
static __inline request_t *
|
||||
|
@ -145,7 +145,7 @@ static void mpt_target_start_io(struct mpt_softc *, union ccb *);
|
||||
static cam_status mpt_abort_target_ccb(struct mpt_softc *, union ccb *);
|
||||
static int mpt_abort_target_cmd(struct mpt_softc *, request_t *);
|
||||
static void mpt_scsi_tgt_status(struct mpt_softc *, union ccb *, request_t *,
|
||||
uint8_t, uint8_t const *);
|
||||
uint8_t, uint8_t const *, u_int);
|
||||
static void
|
||||
mpt_scsi_tgt_tsk_mgmt(struct mpt_softc *, request_t *, mpt_task_mgmt_t,
|
||||
tgt_resource_t *, int);
|
||||
@ -4168,6 +4168,7 @@ mpt_post_target_command(struct mpt_softc *mpt, request_t *req, int ioindex)
|
||||
fc = req->req_vbuf;
|
||||
fc->BufferCount = 1;
|
||||
fc->Function = MPI_FUNCTION_TARGET_CMD_BUFFER_POST;
|
||||
fc->BufferLength = MIN(MPT_REQUEST_AREA - MPT_RQSL(mpt), UINT8_MAX);
|
||||
fc->MsgContext = htole32(req->index | mpt->scsi_tgt_handler_id);
|
||||
|
||||
cb = &fc->Buffer[0];
|
||||
@ -4458,8 +4459,6 @@ mpt_target_start_io(struct mpt_softc *mpt, union ccb *ccb)
|
||||
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
|
||||
}
|
||||
} else {
|
||||
uint8_t *sp = NULL, sense[MPT_SENSE_SIZE];
|
||||
|
||||
/*
|
||||
* XXX: I don't know why this seems to happen, but
|
||||
* XXX: completing the CCB seems to make things happy.
|
||||
@ -4476,12 +4475,10 @@ mpt_target_start_io(struct mpt_softc *mpt, union ccb *ccb)
|
||||
xpt_done(ccb);
|
||||
return;
|
||||
}
|
||||
if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
|
||||
sp = sense;
|
||||
memcpy(sp, &csio->sense_data,
|
||||
min(csio->sense_len, MPT_SENSE_SIZE));
|
||||
}
|
||||
mpt_scsi_tgt_status(mpt, ccb, cmd_req, csio->scsi_status, sp);
|
||||
mpt_scsi_tgt_status(mpt, ccb, cmd_req, csio->scsi_status,
|
||||
(void *)&csio->sense_data,
|
||||
(ccb->ccb_h.flags & CAM_SEND_SENSE) ?
|
||||
csio->sense_len : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4503,7 +4500,7 @@ mpt_scsi_tgt_local(struct mpt_softc *mpt, request_t *cmd_req,
|
||||
tgt = MPT_TGT_STATE(mpt, cmd_req);
|
||||
if (length == 0 || tgt->resid == 0) {
|
||||
tgt->resid = 0;
|
||||
mpt_scsi_tgt_status(mpt, NULL, cmd_req, 0, NULL);
|
||||
mpt_scsi_tgt_status(mpt, NULL, cmd_req, 0, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4656,7 +4653,7 @@ mpt_abort_target_cmd(struct mpt_softc *mpt, request_t *cmd_req)
|
||||
|
||||
static void
|
||||
mpt_scsi_tgt_status(struct mpt_softc *mpt, union ccb *ccb, request_t *cmd_req,
|
||||
uint8_t status, uint8_t const *sense_data)
|
||||
uint8_t status, uint8_t const *sense_data, u_int sense_len)
|
||||
{
|
||||
uint8_t *cmd_vbuf;
|
||||
mpt_tgt_state_t *tgt;
|
||||
@ -4730,37 +4727,22 @@ mpt_scsi_tgt_status(struct mpt_softc *mpt, union ccb *ccb, request_t *cmd_req,
|
||||
*/
|
||||
memset(rsp, 0, sizeof (MPI_TARGET_FCP_RSP_BUFFER));
|
||||
|
||||
rsp[2] = status;
|
||||
if (tgt->resid) {
|
||||
rsp[2] |= 0x800; /* XXXX NEED MNEMONIC!!!! */
|
||||
rsp[3] = htobe32(tgt->resid);
|
||||
#ifdef WE_TRUST_AUTO_GOOD_STATUS
|
||||
resplen = sizeof (MPI_TARGET_FCP_RSP_BUFFER);
|
||||
#endif
|
||||
}
|
||||
if (status == SCSI_STATUS_CHECK_COND) {
|
||||
int i;
|
||||
|
||||
rsp[2] |= 0x200; /* XXXX NEED MNEMONIC!!!! */
|
||||
rsp[4] = htobe32(MPT_SENSE_SIZE);
|
||||
if (sense_data) {
|
||||
memcpy(&rsp[8], sense_data, MPT_SENSE_SIZE);
|
||||
} else {
|
||||
mpt_prt(mpt, "mpt_scsi_tgt_status: CHECK CONDI"
|
||||
"TION but no sense data?\n");
|
||||
memset(&rsp, 0, MPT_SENSE_SIZE);
|
||||
}
|
||||
for (i = 8; i < (8 + (MPT_SENSE_SIZE >> 2)); i++) {
|
||||
rsp[i] = htobe32(rsp[i]);
|
||||
}
|
||||
#ifdef WE_TRUST_AUTO_GOOD_STATUS
|
||||
resplen = sizeof (MPI_TARGET_FCP_RSP_BUFFER);
|
||||
#endif
|
||||
}
|
||||
rsp[2] = htobe32(status);
|
||||
#define MIN_FCP_RESPONSE_SIZE 24
|
||||
#ifndef WE_TRUST_AUTO_GOOD_STATUS
|
||||
resplen = sizeof (MPI_TARGET_FCP_RSP_BUFFER);
|
||||
resplen = MIN_FCP_RESPONSE_SIZE;
|
||||
#endif
|
||||
rsp[2] = htobe32(rsp[2]);
|
||||
if (tgt->resid) {
|
||||
rsp[2] |= htobe32(0x800); /* XXXX NEED MNEMONIC!!!! */
|
||||
rsp[3] = htobe32(tgt->resid);
|
||||
resplen = MIN_FCP_RESPONSE_SIZE;
|
||||
}
|
||||
if (sense_len > 0) {
|
||||
rsp[2] |= htobe32(0x200); /* XXXX NEED MNEMONIC!!!! */
|
||||
rsp[4] = htobe32(sense_len);
|
||||
memcpy(&rsp[6], sense_data, sense_len);
|
||||
resplen = MIN_FCP_RESPONSE_SIZE + sense_len;
|
||||
}
|
||||
} else if (mpt->is_sas) {
|
||||
PTR_MPI_TARGET_SSP_CMD_BUFFER ssp =
|
||||
(PTR_MPI_TARGET_SSP_CMD_BUFFER) cmd_vbuf;
|
||||
@ -4795,9 +4777,9 @@ mpt_scsi_tgt_status(struct mpt_softc *mpt, union ccb *ccb, request_t *cmd_req,
|
||||
}
|
||||
|
||||
mpt_lprt(mpt, MPT_PRT_DEBUG,
|
||||
"STATUS_CCB %p (wit%s sense) tag %x req %p:%u resid %u\n",
|
||||
ccb, sense_data?"h" : "hout", ccb? ccb->csio.tag_id : -1, req,
|
||||
req->serno, tgt->resid);
|
||||
"STATUS_CCB %p (with%s sense) tag %x req %p:%u resid %u\n",
|
||||
ccb, sense_len > 0 ? "" : "out", ccb ? ccb->csio.tag_id : -1,
|
||||
req, req->serno, tgt->resid);
|
||||
if (ccb) {
|
||||
ccb->ccb_h.status = CAM_SIM_QUEUED | CAM_REQ_INPROG;
|
||||
mpt_req_timeout(req, SBT_1S * 60, mpt_timeout, ccb);
|
||||
@ -4816,7 +4798,7 @@ mpt_scsi_tgt_tsk_mgmt(struct mpt_softc *mpt, request_t *req, mpt_task_mgmt_t fc,
|
||||
inot = (struct ccb_immediate_notify *) STAILQ_FIRST(&trtp->inots);
|
||||
if (inot == NULL) {
|
||||
mpt_lprt(mpt, MPT_PRT_WARN, "no INOTSs- sending back BSY\n");
|
||||
mpt_scsi_tgt_status(mpt, NULL, req, SCSI_STATUS_BUSY, NULL);
|
||||
mpt_scsi_tgt_status(mpt, NULL, req, SCSI_STATUS_BUSY, NULL, 0);
|
||||
return;
|
||||
}
|
||||
STAILQ_REMOVE_HEAD(&trtp->inots, sim_links.stqe);
|
||||
@ -4930,8 +4912,8 @@ mpt_scsi_tgt_atio(struct mpt_softc *mpt, request_t *req, uint32_t reply_desc)
|
||||
default:
|
||||
mpt_prt(mpt, "CORRUPTED TASK MGMT BITS: 0x%x\n",
|
||||
fc->FcpCntl[2]);
|
||||
mpt_scsi_tgt_status(mpt, 0, req,
|
||||
SCSI_STATUS_OK, 0);
|
||||
mpt_scsi_tgt_status(mpt, NULL, req,
|
||||
SCSI_STATUS_OK, NULL, 0);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -5005,23 +4987,21 @@ mpt_scsi_tgt_atio(struct mpt_softc *mpt, request_t *req, uint32_t reply_desc)
|
||||
* REPORT LUNS gets illegal command.
|
||||
* All other commands get 'no such device'.
|
||||
*/
|
||||
uint8_t *sp, cond, buf[MPT_SENSE_SIZE];
|
||||
uint8_t sense[MPT_SENSE_SIZE];
|
||||
size_t len;
|
||||
|
||||
memset(buf, 0, MPT_SENSE_SIZE);
|
||||
cond = SCSI_STATUS_CHECK_COND;
|
||||
buf[0] = 0xf0;
|
||||
buf[2] = 0x5;
|
||||
buf[7] = 0x8;
|
||||
sp = buf;
|
||||
memset(sense, 0, sizeof(sense));
|
||||
sense[0] = 0xf0;
|
||||
sense[2] = 0x5;
|
||||
sense[7] = 0x8;
|
||||
tgt->tag_id = MPT_MAKE_TAGID(mpt, req, ioindex);
|
||||
|
||||
switch (cdbp[0]) {
|
||||
case INQUIRY:
|
||||
{
|
||||
if (cdbp[1] != 0) {
|
||||
buf[12] = 0x26;
|
||||
buf[13] = 0x01;
|
||||
sense[12] = 0x26;
|
||||
sense[13] = 0x01;
|
||||
break;
|
||||
}
|
||||
len = min(tgt->resid, cdbp[4]);
|
||||
@ -5034,27 +5014,28 @@ mpt_scsi_tgt_atio(struct mpt_softc *mpt, request_t *req, uint32_t reply_desc)
|
||||
}
|
||||
case REQUEST_SENSE:
|
||||
{
|
||||
buf[2] = 0x0;
|
||||
sense[2] = 0x0;
|
||||
len = min(tgt->resid, cdbp[4]);
|
||||
len = min(len, sizeof (buf));
|
||||
len = min(len, sizeof (sense));
|
||||
mpt_lprt(mpt, MPT_PRT_DEBUG,
|
||||
"local reqsense %ld bytes\n", (long) len);
|
||||
mpt_scsi_tgt_local(mpt, req, lun, 1,
|
||||
buf, len);
|
||||
sense, len);
|
||||
return;
|
||||
}
|
||||
case REPORT_LUNS:
|
||||
mpt_lprt(mpt, MPT_PRT_DEBUG, "REPORT LUNS\n");
|
||||
buf[12] = 0x26;
|
||||
sense[12] = 0x26;
|
||||
return;
|
||||
default:
|
||||
mpt_lprt(mpt, MPT_PRT_DEBUG,
|
||||
"CMD 0x%x to unmanaged lun %jx\n",
|
||||
cdbp[0], (uintmax_t)lun);
|
||||
buf[12] = 0x25;
|
||||
sense[12] = 0x25;
|
||||
break;
|
||||
}
|
||||
mpt_scsi_tgt_status(mpt, NULL, req, cond, sp);
|
||||
mpt_scsi_tgt_status(mpt, NULL, req,
|
||||
SCSI_STATUS_CHECK_COND, sense, sizeof(sense));
|
||||
return;
|
||||
}
|
||||
/* otherwise, leave trtp NULL */
|
||||
@ -5069,8 +5050,8 @@ mpt_scsi_tgt_atio(struct mpt_softc *mpt, request_t *req, uint32_t reply_desc)
|
||||
if (trtp == NULL) {
|
||||
mpt_prt(mpt, "task mgmt function %x but no listener\n",
|
||||
fct);
|
||||
mpt_scsi_tgt_status(mpt, 0, req,
|
||||
SCSI_STATUS_OK, 0);
|
||||
mpt_scsi_tgt_status(mpt, NULL, req,
|
||||
SCSI_STATUS_OK, NULL, 0);
|
||||
} else {
|
||||
mpt_scsi_tgt_tsk_mgmt(mpt, req, fct, trtp,
|
||||
GET_INITIATOR_INDEX(reply_desc));
|
||||
@ -5086,7 +5067,7 @@ mpt_scsi_tgt_atio(struct mpt_softc *mpt, request_t *req, uint32_t reply_desc)
|
||||
mpt->tenabled? "QUEUE FULL" : "BUSY");
|
||||
mpt_scsi_tgt_status(mpt, NULL, req,
|
||||
mpt->tenabled? SCSI_STATUS_QUEUE_FULL : SCSI_STATUS_BUSY,
|
||||
NULL);
|
||||
NULL, 0);
|
||||
return;
|
||||
}
|
||||
STAILQ_REMOVE_HEAD(&trtp->atios, sim_links.stqe);
|
||||
@ -5098,7 +5079,7 @@ mpt_scsi_tgt_atio(struct mpt_softc *mpt, request_t *req, uint32_t reply_desc)
|
||||
atiop->ccb_h.target_lun = lun;
|
||||
atiop->sense_len = 0;
|
||||
atiop->init_id = GET_INITIATOR_INDEX(reply_desc);
|
||||
atiop->cdb_len = mpt_cdblen(cdbp[0], 16);
|
||||
atiop->cdb_len = 16;
|
||||
memcpy(atiop->cdb_io.cdb_bytes, cdbp, atiop->cdb_len);
|
||||
|
||||
/*
|
||||
@ -5179,8 +5160,6 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req,
|
||||
break;
|
||||
case TGT_STATE_MOVING_DATA:
|
||||
{
|
||||
uint8_t *sp = NULL, sense[MPT_SENSE_SIZE];
|
||||
|
||||
ccb = tgt->ccb;
|
||||
if (tgt->req == NULL) {
|
||||
panic("mpt: turbo target reply with null "
|
||||
@ -5200,12 +5179,12 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req,
|
||||
mpt_free_request(mpt, tgt->req);
|
||||
tgt->req = NULL;
|
||||
mpt_scsi_tgt_status(mpt, NULL, req,
|
||||
0, NULL);
|
||||
0, NULL, 0);
|
||||
return (TRUE);
|
||||
}
|
||||
tgt->ccb = NULL;
|
||||
tgt->nxfers++;
|
||||
mpt_req_untimeout(req, mpt_timeout, ccb);
|
||||
mpt_req_untimeout(tgt->req, mpt_timeout, ccb);
|
||||
mpt_lprt(mpt, MPT_PRT_DEBUG,
|
||||
"TARGET_ASSIST %p (req %p:%u) done tag 0x%x\n",
|
||||
ccb, tgt->req, tgt->req->serno, ccb->csio.tag_id);
|
||||
@ -5241,13 +5220,11 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req,
|
||||
/*
|
||||
* Otherwise, send status (and sense)
|
||||
*/
|
||||
if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
|
||||
sp = sense;
|
||||
memcpy(sp, &ccb->csio.sense_data,
|
||||
min(ccb->csio.sense_len, MPT_SENSE_SIZE));
|
||||
}
|
||||
mpt_scsi_tgt_status(mpt, ccb, req,
|
||||
ccb->csio.scsi_status, sp);
|
||||
ccb->csio.scsi_status,
|
||||
(void *)&ccb->csio.sense_data,
|
||||
(ccb->ccb_h.flags & CAM_SEND_SENSE) ?
|
||||
ccb->csio.sense_len : 0);
|
||||
break;
|
||||
}
|
||||
case TGT_STATE_SENDING_STATUS:
|
||||
@ -5268,7 +5245,7 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req,
|
||||
TGT_STATE_MOVING_DATA_AND_STATUS) {
|
||||
tgt->nxfers++;
|
||||
}
|
||||
mpt_req_untimeout(req, mpt_timeout, ccb);
|
||||
mpt_req_untimeout(tgt->req, mpt_timeout, ccb);
|
||||
if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
|
||||
ccb->ccb_h.status |= CAM_SENT_SENSE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user