aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptsas.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2005-10-19 14:01:42 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-10-28 20:09:31 -0400
commitda4fa65596733914b3c21fdffa02593959c67f56 (patch)
tree6a918d3feb6fe266e90dd4634775ae749bade6d0 /drivers/message/fusion/mptsas.c
parent07ba3a954714da10cbd3f6249d93ac2c1df72c4f (diff)
[SCSI] mptsas: add support for PHY resets
Support PHY resets in mptsas. Thanks to Eric for various bug fixes and improvements. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/message/fusion/mptsas.c')
-rw-r--r--drivers/message/fusion/mptsas.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index dcdf0380be86..1c557a09b916 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -83,6 +83,7 @@ MODULE_PARM_DESC(mpt_pt_clear,
83static int mptsasDoneCtx = -1; 83static int mptsasDoneCtx = -1;
84static int mptsasTaskCtx = -1; 84static int mptsasTaskCtx = -1;
85static int mptsasInternalCtx = -1; /* Used only for internal commands */ 85static int mptsasInternalCtx = -1; /* Used only for internal commands */
86static int mptsasMgmtCtx = -1;
86 87
87 88
88/* 89/*
@@ -359,9 +360,92 @@ static int mptsas_get_linkerrors(struct sas_phy *phy)
359 return error; 360 return error;
360} 361}
361 362
363static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
364 MPT_FRAME_HDR *reply)
365{
366 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
367 if (reply != NULL) {
368 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
369 memcpy(ioc->sas_mgmt.reply, reply,
370 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
371 }
372 complete(&ioc->sas_mgmt.done);
373 return 1;
374}
375
376static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
377{
378 MPT_ADAPTER *ioc = phy_to_ioc(phy);
379 SasIoUnitControlRequest_t *req;
380 SasIoUnitControlReply_t *reply;
381 MPT_FRAME_HDR *mf;
382 MPIHeader_t *hdr;
383 unsigned long timeleft;
384 int error = -ERESTARTSYS;
385
386 /* not implemented for expanders */
387 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
388 return -ENXIO;
389
390 if (down_interruptible(&ioc->sas_mgmt.mutex))
391 goto out;
392
393 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
394 if (!mf) {
395 error = -ENOMEM;
396 goto out_unlock;
397 }
398
399 hdr = (MPIHeader_t *) mf;
400 req = (SasIoUnitControlRequest_t *)mf;
401 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
402 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
403 req->MsgContext = hdr->MsgContext;
404 req->Operation = hard_reset ?
405 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
406 req->PhyNum = phy->identify.phy_identifier;
407
408 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
409
410 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
411 10 * HZ);
412 if (!timeleft) {
413 /* On timeout reset the board */
414 mpt_free_msg_frame(ioc, mf);
415 mpt_HardResetHandler(ioc, CAN_SLEEP);
416 error = -ETIMEDOUT;
417 goto out_unlock;
418 }
419
420 /* a reply frame is expected */
421 if ((ioc->sas_mgmt.status &
422 MPT_IOCTL_STATUS_RF_VALID) == 0) {
423 error = -ENXIO;
424 goto out_unlock;
425 }
426
427 /* process the completed Reply Message Frame */
428 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
429 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
430 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
431 __FUNCTION__,
432 reply->IOCStatus,
433 reply->IOCLogInfo);
434 error = -ENXIO;
435 goto out_unlock;
436 }
437
438 error = 0;
439
440 out_unlock:
441 up(&ioc->sas_mgmt.mutex);
442 out:
443 return error;
444}
362 445
363static struct sas_function_template mptsas_transport_functions = { 446static struct sas_function_template mptsas_transport_functions = {
364 .get_linkerrors = mptsas_get_linkerrors, 447 .get_linkerrors = mptsas_get_linkerrors,
448 .phy_reset = mptsas_phy_reset,
365}; 449};
366 450
367static struct scsi_transport_template *mptsas_transport_template; 451static struct scsi_transport_template *mptsas_transport_template;
@@ -1105,6 +1189,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1105 sh->unique_id = ioc->id; 1189 sh->unique_id = ioc->id;
1106 1190
1107 INIT_LIST_HEAD(&ioc->sas_topology); 1191 INIT_LIST_HEAD(&ioc->sas_topology);
1192 init_MUTEX(&ioc->sas_mgmt.mutex);
1193 init_completion(&ioc->sas_mgmt.done);
1108 1194
1109 /* Verify that we won't exceed the maximum 1195 /* Verify that we won't exceed the maximum
1110 * number of chain buffers 1196 * number of chain buffers
@@ -1291,6 +1377,7 @@ mptsas_init(void)
1291 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); 1377 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
1292 mptsasInternalCtx = 1378 mptsasInternalCtx =
1293 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); 1379 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
1380 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
1294 1381
1295 if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) { 1382 if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
1296 devtprintk((KERN_INFO MYNAM 1383 devtprintk((KERN_INFO MYNAM
@@ -1314,6 +1401,7 @@ mptsas_exit(void)
1314 mpt_reset_deregister(mptsasDoneCtx); 1401 mpt_reset_deregister(mptsasDoneCtx);
1315 mpt_event_deregister(mptsasDoneCtx); 1402 mpt_event_deregister(mptsasDoneCtx);
1316 1403
1404 mpt_deregister(mptsasMgmtCtx);
1317 mpt_deregister(mptsasInternalCtx); 1405 mpt_deregister(mptsasInternalCtx);
1318 mpt_deregister(mptsasTaskCtx); 1406 mpt_deregister(mptsasTaskCtx);
1319 mpt_deregister(mptsasDoneCtx); 1407 mpt_deregister(mptsasDoneCtx);