diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-12 12:50:42 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-12 12:50:42 -0400 |
| commit | c9b8af00ff71f86ff3d092cc60ca673e1d0eae5b (patch) | |
| tree | 25cc016481cc693552bebb4040041817280c2ccf /drivers/message | |
| parent | c59a264c9e932c828d533497e286b89e43c8d1be (diff) | |
| parent | 82681a318f9f028ea64e61f24bbd9ac535531921 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (154 commits)
[SCSI] osd: Remove out-of-tree left overs
[SCSI] libosd: Use REQ_QUIET requests.
[SCSI] osduld: use filp_open() when looking up an osd-device
[SCSI] libosd: Define an osd_dev wrapper to retrieve the request_queue
[SCSI] libosd: osd_req_{read,write} takes a length parameter
[SCSI] libosd: Let _osd_req_finalize_data_integrity receive number of out_bytes
[SCSI] libosd: osd_req_{read,write}_kern new API
[SCSI] libosd: Better printout of OSD target system information
[SCSI] libosd: OSD2r05: Attribute definitions
[SCSI] libosd: OSD2r05: Additional command enums
[SCSI] mpt fusion: fix up doc book comments
[SCSI] mpt fusion: Added support for Broadcast primitives Event handling
[SCSI] mpt fusion: Queue full event handling
[SCSI] mpt fusion: RAID device handling and Dual port Raid support is added
[SCSI] mpt fusion: Put IOC into ready state if it not already in ready state
[SCSI] mpt fusion: Code Cleanup patch
[SCSI] mpt fusion: Rescan SAS topology added
[SCSI] mpt fusion: SAS topology scan changes, expander events
[SCSI] mpt fusion: Firmware event implementation using seperate WorkQueue
[SCSI] mpt fusion: rewrite of ioctl_cmds internal generated function
...
Diffstat (limited to 'drivers/message')
| -rw-r--r-- | drivers/message/fusion/mptbase.c | 1571 | ||||
| -rw-r--r-- | drivers/message/fusion/mptbase.h | 180 | ||||
| -rw-r--r-- | drivers/message/fusion/mptctl.c | 692 | ||||
| -rw-r--r-- | drivers/message/fusion/mptdebug.h | 3 | ||||
| -rw-r--r-- | drivers/message/fusion/mptfc.c | 15 | ||||
| -rw-r--r-- | drivers/message/fusion/mptsas.c | 3114 | ||||
| -rw-r--r-- | drivers/message/fusion/mptsas.h | 41 | ||||
| -rw-r--r-- | drivers/message/fusion/mptscsih.c | 1329 | ||||
| -rw-r--r-- | drivers/message/fusion/mptscsih.h | 7 | ||||
| -rw-r--r-- | drivers/message/fusion/mptspi.c | 71 |
10 files changed, 4569 insertions, 2454 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 5d496a99e034..44b931504457 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
| @@ -146,7 +146,6 @@ static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS]; | |||
| 146 | static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS]; | 146 | static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS]; |
| 147 | static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS]; | 147 | static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS]; |
| 148 | 148 | ||
| 149 | static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq); | ||
| 150 | 149 | ||
| 151 | /* | 150 | /* |
| 152 | * Driver Callback Index's | 151 | * Driver Callback Index's |
| @@ -159,7 +158,8 @@ static u8 last_drv_idx; | |||
| 159 | * Forward protos... | 158 | * Forward protos... |
| 160 | */ | 159 | */ |
| 161 | static irqreturn_t mpt_interrupt(int irq, void *bus_id); | 160 | static irqreturn_t mpt_interrupt(int irq, void *bus_id); |
| 162 | static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); | 161 | static int mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, |
| 162 | MPT_FRAME_HDR *reply); | ||
| 163 | static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, | 163 | static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, |
| 164 | u32 *req, int replyBytes, u16 *u16reply, int maxwait, | 164 | u32 *req, int replyBytes, u16 *u16reply, int maxwait, |
| 165 | int sleepFlag); | 165 | int sleepFlag); |
| @@ -190,9 +190,9 @@ static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); | |||
| 190 | static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); | 190 | static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); |
| 191 | static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); | 191 | static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); |
| 192 | static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); | 192 | static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); |
| 193 | static void mpt_timer_expired(unsigned long data); | ||
| 194 | static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc); | 193 | static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc); |
| 195 | static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); | 194 | static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, |
| 195 | int sleepFlag); | ||
| 196 | static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); | 196 | static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); |
| 197 | static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag); | 197 | static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag); |
| 198 | static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init); | 198 | static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init); |
| @@ -207,8 +207,8 @@ static int procmpt_iocinfo_read(char *buf, char **start, off_t offset, | |||
| 207 | #endif | 207 | #endif |
| 208 | static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); | 208 | static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); |
| 209 | 209 | ||
| 210 | //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); | 210 | static int ProcessEventNotification(MPT_ADAPTER *ioc, |
| 211 | static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); | 211 | EventNotificationReply_t *evReply, int *evHandlers); |
| 212 | static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); | 212 | static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); |
| 213 | static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); | 213 | static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); |
| 214 | static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); | 214 | static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); |
| @@ -277,6 +277,56 @@ mpt_get_cb_idx(MPT_DRIVER_CLASS dclass) | |||
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | /** | 279 | /** |
| 280 | * mpt_is_discovery_complete - determine if discovery has completed | ||
| 281 | * @ioc: per adatper instance | ||
| 282 | * | ||
| 283 | * Returns 1 when discovery completed, else zero. | ||
| 284 | */ | ||
| 285 | static int | ||
| 286 | mpt_is_discovery_complete(MPT_ADAPTER *ioc) | ||
| 287 | { | ||
| 288 | ConfigExtendedPageHeader_t hdr; | ||
| 289 | CONFIGPARMS cfg; | ||
| 290 | SasIOUnitPage0_t *buffer; | ||
| 291 | dma_addr_t dma_handle; | ||
| 292 | int rc = 0; | ||
| 293 | |||
| 294 | memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t)); | ||
| 295 | memset(&cfg, 0, sizeof(CONFIGPARMS)); | ||
| 296 | hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; | ||
| 297 | hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; | ||
| 298 | hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | ||
| 299 | cfg.cfghdr.ehdr = &hdr; | ||
| 300 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 301 | |||
| 302 | if ((mpt_config(ioc, &cfg))) | ||
| 303 | goto out; | ||
| 304 | if (!hdr.ExtPageLength) | ||
| 305 | goto out; | ||
| 306 | |||
| 307 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
| 308 | &dma_handle); | ||
| 309 | if (!buffer) | ||
| 310 | goto out; | ||
| 311 | |||
| 312 | cfg.physAddr = dma_handle; | ||
| 313 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 314 | |||
| 315 | if ((mpt_config(ioc, &cfg))) | ||
| 316 | goto out_free_consistent; | ||
| 317 | |||
| 318 | if (!(buffer->PhyData[0].PortFlags & | ||
| 319 | MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS)) | ||
| 320 | rc = 1; | ||
| 321 | |||
| 322 | out_free_consistent: | ||
| 323 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
| 324 | buffer, dma_handle); | ||
| 325 | out: | ||
| 326 | return rc; | ||
| 327 | } | ||
| 328 | |||
| 329 | /** | ||
| 280 | * mpt_fault_reset_work - work performed on workq after ioc fault | 330 | * mpt_fault_reset_work - work performed on workq after ioc fault |
| 281 | * @work: input argument, used to derive ioc | 331 | * @work: input argument, used to derive ioc |
| 282 | * | 332 | * |
| @@ -290,7 +340,7 @@ mpt_fault_reset_work(struct work_struct *work) | |||
| 290 | int rc; | 340 | int rc; |
| 291 | unsigned long flags; | 341 | unsigned long flags; |
| 292 | 342 | ||
| 293 | if (ioc->diagPending || !ioc->active) | 343 | if (ioc->ioc_reset_in_progress || !ioc->active) |
| 294 | goto out; | 344 | goto out; |
| 295 | 345 | ||
| 296 | ioc_raw_state = mpt_GetIocState(ioc, 0); | 346 | ioc_raw_state = mpt_GetIocState(ioc, 0); |
| @@ -307,6 +357,12 @@ mpt_fault_reset_work(struct work_struct *work) | |||
| 307 | printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after " | 357 | printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after " |
| 308 | "reset (%04xh)\n", ioc->name, ioc_raw_state & | 358 | "reset (%04xh)\n", ioc->name, ioc_raw_state & |
| 309 | MPI_DOORBELL_DATA_MASK); | 359 | MPI_DOORBELL_DATA_MASK); |
| 360 | } else if (ioc->bus_type == SAS && ioc->sas_discovery_quiesce_io) { | ||
| 361 | if ((mpt_is_discovery_complete(ioc))) { | ||
| 362 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "clearing " | ||
| 363 | "discovery_quiesce_io flag\n", ioc->name)); | ||
| 364 | ioc->sas_discovery_quiesce_io = 0; | ||
| 365 | } | ||
| 310 | } | 366 | } |
| 311 | 367 | ||
| 312 | out: | 368 | out: |
| @@ -317,11 +373,11 @@ mpt_fault_reset_work(struct work_struct *work) | |||
| 317 | ioc = ioc->alt_ioc; | 373 | ioc = ioc->alt_ioc; |
| 318 | 374 | ||
| 319 | /* rearm the timer */ | 375 | /* rearm the timer */ |
| 320 | spin_lock_irqsave(&ioc->fault_reset_work_lock, flags); | 376 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
| 321 | if (ioc->reset_work_q) | 377 | if (ioc->reset_work_q) |
| 322 | queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work, | 378 | queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work, |
| 323 | msecs_to_jiffies(MPT_POLLING_INTERVAL)); | 379 | msecs_to_jiffies(MPT_POLLING_INTERVAL)); |
| 324 | spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags); | 380 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); |
| 325 | } | 381 | } |
| 326 | 382 | ||
| 327 | 383 | ||
| @@ -501,9 +557,9 @@ mpt_interrupt(int irq, void *bus_id) | |||
| 501 | 557 | ||
| 502 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 558 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 503 | /** | 559 | /** |
| 504 | * mpt_base_reply - MPT base driver's callback routine | 560 | * mptbase_reply - MPT base driver's callback routine |
| 505 | * @ioc: Pointer to MPT_ADAPTER structure | 561 | * @ioc: Pointer to MPT_ADAPTER structure |
| 506 | * @mf: Pointer to original MPT request frame | 562 | * @req: Pointer to original MPT request frame |
| 507 | * @reply: Pointer to MPT reply frame (NULL if TurboReply) | 563 | * @reply: Pointer to MPT reply frame (NULL if TurboReply) |
| 508 | * | 564 | * |
| 509 | * MPT base driver's callback routine; all base driver | 565 | * MPT base driver's callback routine; all base driver |
| @@ -514,122 +570,49 @@ mpt_interrupt(int irq, void *bus_id) | |||
| 514 | * should be freed, or 0 if it shouldn't. | 570 | * should be freed, or 0 if it shouldn't. |
| 515 | */ | 571 | */ |
| 516 | static int | 572 | static int |
| 517 | mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) | 573 | mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) |
| 518 | { | 574 | { |
| 575 | EventNotificationReply_t *pEventReply; | ||
| 576 | u8 event; | ||
| 577 | int evHandlers; | ||
| 519 | int freereq = 1; | 578 | int freereq = 1; |
| 520 | u8 func; | ||
| 521 | 579 | ||
| 522 | dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply() called\n", ioc->name)); | 580 | switch (reply->u.hdr.Function) { |
| 523 | #ifdef CONFIG_FUSION_LOGGING | 581 | case MPI_FUNCTION_EVENT_NOTIFICATION: |
| 524 | if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) && | 582 | pEventReply = (EventNotificationReply_t *)reply; |
| 525 | !(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) { | 583 | evHandlers = 0; |
| 526 | dmfprintk(ioc, printk(MYIOC_s_INFO_FMT ": Original request frame (@%p) header\n", | 584 | ProcessEventNotification(ioc, pEventReply, &evHandlers); |
| 527 | ioc->name, mf)); | 585 | event = le32_to_cpu(pEventReply->Event) & 0xFF; |
| 528 | DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf); | 586 | if (pEventReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) |
| 529 | } | ||
| 530 | #endif | ||
| 531 | |||
| 532 | func = reply->u.hdr.Function; | ||
| 533 | dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, Function=%02Xh\n", | ||
| 534 | ioc->name, func)); | ||
| 535 | |||
| 536 | if (func == MPI_FUNCTION_EVENT_NOTIFICATION) { | ||
| 537 | EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply; | ||
| 538 | int evHandlers = 0; | ||
| 539 | int results; | ||
| 540 | |||
| 541 | results = ProcessEventNotification(ioc, pEvReply, &evHandlers); | ||
| 542 | if (results != evHandlers) { | ||
| 543 | /* CHECKME! Any special handling needed here? */ | ||
| 544 | devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", | ||
| 545 | ioc->name, evHandlers, results)); | ||
| 546 | } | ||
| 547 | |||
| 548 | /* | ||
| 549 | * Hmmm... It seems that EventNotificationReply is an exception | ||
| 550 | * to the rule of one reply per request. | ||
| 551 | */ | ||
| 552 | if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) { | ||
| 553 | freereq = 0; | 587 | freereq = 0; |
| 554 | } else { | 588 | if (event != MPI_EVENT_EVENT_CHANGE) |
| 555 | devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", | 589 | break; |
| 556 | ioc->name, pEvReply)); | 590 | case MPI_FUNCTION_CONFIG: |
| 557 | } | 591 | case MPI_FUNCTION_SAS_IO_UNIT_CONTROL: |
| 558 | 592 | ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; | |
| 559 | #ifdef CONFIG_PROC_FS | 593 | if (reply) { |
| 560 | // LogEvent(ioc, pEvReply); | 594 | ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID; |
| 561 | #endif | 595 | memcpy(ioc->mptbase_cmds.reply, reply, |
| 562 | 596 | min(MPT_DEFAULT_FRAME_SIZE, | |
| 563 | } else if (func == MPI_FUNCTION_EVENT_ACK) { | 597 | 4 * reply->u.reply.MsgLength)); |
| 564 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, EventAck reply received\n", | ||
| 565 | ioc->name)); | ||
| 566 | } else if (func == MPI_FUNCTION_CONFIG) { | ||
| 567 | CONFIGPARMS *pCfg; | ||
| 568 | unsigned long flags; | ||
| 569 | |||
| 570 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "config_complete (mf=%p,mr=%p)\n", | ||
| 571 | ioc->name, mf, reply)); | ||
| 572 | |||
| 573 | pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *))); | ||
| 574 | |||
| 575 | if (pCfg) { | ||
| 576 | /* disable timer and remove from linked list */ | ||
| 577 | del_timer(&pCfg->timer); | ||
| 578 | |||
| 579 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
| 580 | list_del(&pCfg->linkage); | ||
| 581 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
| 582 | |||
| 583 | /* | ||
| 584 | * If IOC Status is SUCCESS, save the header | ||
| 585 | * and set the status code to GOOD. | ||
| 586 | */ | ||
| 587 | pCfg->status = MPT_CONFIG_ERROR; | ||
| 588 | if (reply) { | ||
| 589 | ConfigReply_t *pReply = (ConfigReply_t *)reply; | ||
| 590 | u16 status; | ||
| 591 | |||
| 592 | status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
| 593 | dcprintk(ioc, printk(MYIOC_s_NOTE_FMT " IOCStatus=%04xh, IOCLogInfo=%08xh\n", | ||
| 594 | ioc->name, status, le32_to_cpu(pReply->IOCLogInfo))); | ||
| 595 | |||
| 596 | pCfg->status = status; | ||
| 597 | if (status == MPI_IOCSTATUS_SUCCESS) { | ||
| 598 | if ((pReply->Header.PageType & | ||
| 599 | MPI_CONFIG_PAGETYPE_MASK) == | ||
| 600 | MPI_CONFIG_PAGETYPE_EXTENDED) { | ||
| 601 | pCfg->cfghdr.ehdr->ExtPageLength = | ||
| 602 | le16_to_cpu(pReply->ExtPageLength); | ||
| 603 | pCfg->cfghdr.ehdr->ExtPageType = | ||
| 604 | pReply->ExtPageType; | ||
| 605 | } | ||
| 606 | pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion; | ||
| 607 | |||
| 608 | /* If this is a regular header, save PageLength. */ | ||
| 609 | /* LMP Do this better so not using a reserved field! */ | ||
| 610 | pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength; | ||
| 611 | pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber; | ||
| 612 | pCfg->cfghdr.hdr->PageType = pReply->Header.PageType; | ||
| 613 | } | ||
| 614 | } | ||
| 615 | |||
| 616 | /* | ||
| 617 | * Wake up the original calling thread | ||
| 618 | */ | ||
| 619 | pCfg->wait_done = 1; | ||
| 620 | wake_up(&mpt_waitq); | ||
| 621 | } | 598 | } |
| 622 | } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) { | 599 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) { |
| 623 | /* we should be always getting a reply frame */ | 600 | ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING; |
| 624 | memcpy(ioc->persist_reply_frame, reply, | 601 | complete(&ioc->mptbase_cmds.done); |
| 625 | min(MPT_DEFAULT_FRAME_SIZE, | 602 | } else |
| 626 | 4*reply->u.reply.MsgLength)); | 603 | freereq = 0; |
| 627 | del_timer(&ioc->persist_timer); | 604 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_FREE_MF) |
| 628 | ioc->persist_wait_done = 1; | 605 | freereq = 1; |
| 629 | wake_up(&mpt_waitq); | 606 | break; |
| 630 | } else { | 607 | case MPI_FUNCTION_EVENT_ACK: |
| 631 | printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n", | 608 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 632 | ioc->name, func); | 609 | "EventAck reply received\n", ioc->name)); |
| 610 | break; | ||
| 611 | default: | ||
| 612 | printk(MYIOC_s_ERR_FMT | ||
| 613 | "Unexpected msg function (=%02Xh) reply received!\n", | ||
| 614 | ioc->name, reply->u.hdr.Function); | ||
| 615 | break; | ||
| 633 | } | 616 | } |
| 634 | 617 | ||
| 635 | /* | 618 | /* |
| @@ -988,17 +971,21 @@ mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) | |||
| 988 | 971 | ||
| 989 | /* Put Request back on FreeQ! */ | 972 | /* Put Request back on FreeQ! */ |
| 990 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 973 | spin_lock_irqsave(&ioc->FreeQlock, flags); |
| 991 | mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */ | 974 | if (cpu_to_le32(mf->u.frame.linkage.arg1) == 0xdeadbeaf) |
| 975 | goto out; | ||
| 976 | /* signature to know if this mf is freed */ | ||
| 977 | mf->u.frame.linkage.arg1 = cpu_to_le32(0xdeadbeaf); | ||
| 992 | list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); | 978 | list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); |
| 993 | #ifdef MFCNT | 979 | #ifdef MFCNT |
| 994 | ioc->mfcnt--; | 980 | ioc->mfcnt--; |
| 995 | #endif | 981 | #endif |
| 982 | out: | ||
| 996 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 983 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); |
| 997 | } | 984 | } |
| 998 | 985 | ||
| 999 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 986 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 1000 | /** | 987 | /** |
| 1001 | * mpt_add_sge - Place a simple SGE at address pAddr. | 988 | * mpt_add_sge - Place a simple 32 bit SGE at address pAddr. |
| 1002 | * @pAddr: virtual address for SGE | 989 | * @pAddr: virtual address for SGE |
| 1003 | * @flagslength: SGE flags and data transfer length | 990 | * @flagslength: SGE flags and data transfer length |
| 1004 | * @dma_addr: Physical address | 991 | * @dma_addr: Physical address |
| @@ -1006,23 +993,117 @@ mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) | |||
| 1006 | * This routine places a MPT request frame back on the MPT adapter's | 993 | * This routine places a MPT request frame back on the MPT adapter's |
| 1007 | * FreeQ. | 994 | * FreeQ. |
| 1008 | */ | 995 | */ |
| 1009 | void | 996 | static void |
| 1010 | mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) | 997 | mpt_add_sge(void *pAddr, u32 flagslength, dma_addr_t dma_addr) |
| 1011 | { | 998 | { |
| 1012 | if (sizeof(dma_addr_t) == sizeof(u64)) { | 999 | SGESimple32_t *pSge = (SGESimple32_t *) pAddr; |
| 1013 | SGESimple64_t *pSge = (SGESimple64_t *) pAddr; | 1000 | pSge->FlagsLength = cpu_to_le32(flagslength); |
| 1001 | pSge->Address = cpu_to_le32(dma_addr); | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | /** | ||
| 1005 | * mpt_add_sge_64bit - Place a simple 64 bit SGE at address pAddr. | ||
| 1006 | * @pAddr: virtual address for SGE | ||
| 1007 | * @flagslength: SGE flags and data transfer length | ||
| 1008 | * @dma_addr: Physical address | ||
| 1009 | * | ||
| 1010 | * This routine places a MPT request frame back on the MPT adapter's | ||
| 1011 | * FreeQ. | ||
| 1012 | **/ | ||
| 1013 | static void | ||
| 1014 | mpt_add_sge_64bit(void *pAddr, u32 flagslength, dma_addr_t dma_addr) | ||
| 1015 | { | ||
| 1016 | SGESimple64_t *pSge = (SGESimple64_t *) pAddr; | ||
| 1017 | pSge->Address.Low = cpu_to_le32 | ||
| 1018 | (lower_32_bits((unsigned long)(dma_addr))); | ||
| 1019 | pSge->Address.High = cpu_to_le32 | ||
| 1020 | (upper_32_bits((unsigned long)dma_addr)); | ||
| 1021 | pSge->FlagsLength = cpu_to_le32 | ||
| 1022 | ((flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING)); | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | /** | ||
| 1026 | * mpt_add_sge_64bit_1078 - Place a simple 64 bit SGE at address pAddr | ||
| 1027 | * (1078 workaround). | ||
| 1028 | * @pAddr: virtual address for SGE | ||
| 1029 | * @flagslength: SGE flags and data transfer length | ||
| 1030 | * @dma_addr: Physical address | ||
| 1031 | * | ||
| 1032 | * This routine places a MPT request frame back on the MPT adapter's | ||
| 1033 | * FreeQ. | ||
| 1034 | **/ | ||
| 1035 | static void | ||
| 1036 | mpt_add_sge_64bit_1078(void *pAddr, u32 flagslength, dma_addr_t dma_addr) | ||
| 1037 | { | ||
| 1038 | SGESimple64_t *pSge = (SGESimple64_t *) pAddr; | ||
| 1039 | u32 tmp; | ||
| 1040 | |||
| 1041 | pSge->Address.Low = cpu_to_le32 | ||
| 1042 | (lower_32_bits((unsigned long)(dma_addr))); | ||
| 1043 | tmp = (u32)(upper_32_bits((unsigned long)dma_addr)); | ||
| 1044 | |||
| 1045 | /* | ||
| 1046 | * 1078 errata workaround for the 36GB limitation | ||
| 1047 | */ | ||
| 1048 | if ((((u64)dma_addr + MPI_SGE_LENGTH(flagslength)) >> 32) == 9) { | ||
| 1049 | flagslength |= | ||
| 1050 | MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_LOCAL_ADDRESS); | ||
| 1051 | tmp |= (1<<31); | ||
| 1052 | if (mpt_debug_level & MPT_DEBUG_36GB_MEM) | ||
| 1053 | printk(KERN_DEBUG "1078 P0M2 addressing for " | ||
| 1054 | "addr = 0x%llx len = %d\n", | ||
| 1055 | (unsigned long long)dma_addr, | ||
| 1056 | MPI_SGE_LENGTH(flagslength)); | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | pSge->Address.High = cpu_to_le32(tmp); | ||
| 1060 | pSge->FlagsLength = cpu_to_le32( | ||
| 1061 | (flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING)); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
| 1065 | /** | ||
| 1066 | * mpt_add_chain - Place a 32 bit chain SGE at address pAddr. | ||
| 1067 | * @pAddr: virtual address for SGE | ||
| 1068 | * @next: nextChainOffset value (u32's) | ||
| 1069 | * @length: length of next SGL segment | ||
| 1070 | * @dma_addr: Physical address | ||
| 1071 | * | ||
| 1072 | */ | ||
| 1073 | static void | ||
| 1074 | mpt_add_chain(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr) | ||
| 1075 | { | ||
| 1076 | SGEChain32_t *pChain = (SGEChain32_t *) pAddr; | ||
| 1077 | pChain->Length = cpu_to_le16(length); | ||
| 1078 | pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT; | ||
| 1079 | pChain->NextChainOffset = next; | ||
| 1080 | pChain->Address = cpu_to_le32(dma_addr); | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
| 1084 | /** | ||
| 1085 | * mpt_add_chain_64bit - Place a 64 bit chain SGE at address pAddr. | ||
| 1086 | * @pAddr: virtual address for SGE | ||
| 1087 | * @next: nextChainOffset value (u32's) | ||
| 1088 | * @length: length of next SGL segment | ||
| 1089 | * @dma_addr: Physical address | ||
| 1090 | * | ||
| 1091 | */ | ||
| 1092 | static void | ||
| 1093 | mpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr) | ||
| 1094 | { | ||
| 1095 | SGEChain64_t *pChain = (SGEChain64_t *) pAddr; | ||
| 1014 | u32 tmp = dma_addr & 0xFFFFFFFF; | 1096 | u32 tmp = dma_addr & 0xFFFFFFFF; |
| 1015 | 1097 | ||
| 1016 | pSge->FlagsLength = cpu_to_le32(flagslength); | 1098 | pChain->Length = cpu_to_le16(length); |
| 1017 | pSge->Address.Low = cpu_to_le32(tmp); | 1099 | pChain->Flags = (MPI_SGE_FLAGS_CHAIN_ELEMENT | |
| 1018 | tmp = (u32) ((u64)dma_addr >> 32); | 1100 | MPI_SGE_FLAGS_64_BIT_ADDRESSING); |
| 1019 | pSge->Address.High = cpu_to_le32(tmp); | ||
| 1020 | 1101 | ||
| 1021 | } else { | 1102 | pChain->NextChainOffset = next; |
| 1022 | SGESimple32_t *pSge = (SGESimple32_t *) pAddr; | 1103 | |
| 1023 | pSge->FlagsLength = cpu_to_le32(flagslength); | 1104 | pChain->Address.Low = cpu_to_le32(tmp); |
| 1024 | pSge->Address = cpu_to_le32(dma_addr); | 1105 | tmp = (u32)(upper_32_bits((unsigned long)dma_addr)); |
| 1025 | } | 1106 | pChain->Address.High = cpu_to_le32(tmp); |
| 1026 | } | 1107 | } |
| 1027 | 1108 | ||
| 1028 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1109 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| @@ -1225,7 +1306,7 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init) | |||
| 1225 | } | 1306 | } |
| 1226 | flags_length = flags_length << MPI_SGE_FLAGS_SHIFT; | 1307 | flags_length = flags_length << MPI_SGE_FLAGS_SHIFT; |
| 1227 | flags_length |= ioc->HostPageBuffer_sz; | 1308 | flags_length |= ioc->HostPageBuffer_sz; |
| 1228 | mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma); | 1309 | ioc->add_sge(psge, flags_length, ioc->HostPageBuffer_dma); |
| 1229 | ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE; | 1310 | ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE; |
| 1230 | 1311 | ||
| 1231 | return 0; | 1312 | return 0; |
| @@ -1534,21 +1615,42 @@ mpt_mapresources(MPT_ADAPTER *ioc) | |||
| 1534 | 1615 | ||
| 1535 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); | 1616 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); |
| 1536 | 1617 | ||
| 1537 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) | 1618 | if (sizeof(dma_addr_t) > 4) { |
| 1538 | && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { | 1619 | const uint64_t required_mask = dma_get_required_mask |
| 1539 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | 1620 | (&pdev->dev); |
| 1540 | ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", | 1621 | if (required_mask > DMA_BIT_MASK(32) |
| 1541 | ioc->name)); | 1622 | && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) |
| 1542 | } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) | 1623 | && !pci_set_consistent_dma_mask(pdev, |
| 1543 | && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { | 1624 | DMA_BIT_MASK(64))) { |
| 1544 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | 1625 | ioc->dma_mask = DMA_BIT_MASK(64); |
| 1545 | ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", | 1626 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT |
| 1546 | ioc->name)); | 1627 | ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", |
| 1628 | ioc->name)); | ||
| 1629 | } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) | ||
| 1630 | && !pci_set_consistent_dma_mask(pdev, | ||
| 1631 | DMA_BIT_MASK(32))) { | ||
| 1632 | ioc->dma_mask = DMA_BIT_MASK(32); | ||
| 1633 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | ||
| 1634 | ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", | ||
| 1635 | ioc->name)); | ||
| 1636 | } else { | ||
| 1637 | printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n", | ||
| 1638 | ioc->name, pci_name(pdev)); | ||
| 1639 | return r; | ||
| 1640 | } | ||
| 1547 | } else { | 1641 | } else { |
| 1548 | printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n", | 1642 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) |
| 1549 | ioc->name, pci_name(pdev)); | 1643 | && !pci_set_consistent_dma_mask(pdev, |
| 1550 | pci_release_selected_regions(pdev, ioc->bars); | 1644 | DMA_BIT_MASK(32))) { |
| 1551 | return r; | 1645 | ioc->dma_mask = DMA_BIT_MASK(32); |
| 1646 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | ||
| 1647 | ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", | ||
| 1648 | ioc->name)); | ||
| 1649 | } else { | ||
| 1650 | printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n", | ||
| 1651 | ioc->name, pci_name(pdev)); | ||
| 1652 | return r; | ||
| 1653 | } | ||
| 1552 | } | 1654 | } |
| 1553 | 1655 | ||
| 1554 | mem_phys = msize = 0; | 1656 | mem_phys = msize = 0; |
| @@ -1632,6 +1734,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1632 | 1734 | ||
| 1633 | ioc->id = mpt_ids++; | 1735 | ioc->id = mpt_ids++; |
| 1634 | sprintf(ioc->name, "ioc%d", ioc->id); | 1736 | sprintf(ioc->name, "ioc%d", ioc->id); |
| 1737 | dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n")); | ||
| 1635 | 1738 | ||
| 1636 | /* | 1739 | /* |
| 1637 | * set initial debug level | 1740 | * set initial debug level |
| @@ -1650,14 +1753,36 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1650 | return r; | 1753 | return r; |
| 1651 | } | 1754 | } |
| 1652 | 1755 | ||
| 1756 | /* | ||
| 1757 | * Setting up proper handlers for scatter gather handling | ||
| 1758 | */ | ||
| 1759 | if (ioc->dma_mask == DMA_BIT_MASK(64)) { | ||
| 1760 | if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) | ||
| 1761 | ioc->add_sge = &mpt_add_sge_64bit_1078; | ||
| 1762 | else | ||
| 1763 | ioc->add_sge = &mpt_add_sge_64bit; | ||
| 1764 | ioc->add_chain = &mpt_add_chain_64bit; | ||
| 1765 | ioc->sg_addr_size = 8; | ||
| 1766 | } else { | ||
| 1767 | ioc->add_sge = &mpt_add_sge; | ||
| 1768 | ioc->add_chain = &mpt_add_chain; | ||
| 1769 | ioc->sg_addr_size = 4; | ||
| 1770 | } | ||
| 1771 | ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size; | ||
| 1772 | |||
| 1653 | ioc->alloc_total = sizeof(MPT_ADAPTER); | 1773 | ioc->alloc_total = sizeof(MPT_ADAPTER); |
| 1654 | ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ | 1774 | ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ |
| 1655 | ioc->reply_sz = MPT_REPLY_FRAME_SIZE; | 1775 | ioc->reply_sz = MPT_REPLY_FRAME_SIZE; |
| 1656 | 1776 | ||
| 1657 | ioc->pcidev = pdev; | 1777 | ioc->pcidev = pdev; |
| 1658 | ioc->diagPending = 0; | 1778 | |
| 1659 | spin_lock_init(&ioc->diagLock); | 1779 | spin_lock_init(&ioc->taskmgmt_lock); |
| 1660 | spin_lock_init(&ioc->initializing_hba_lock); | 1780 | mutex_init(&ioc->internal_cmds.mutex); |
| 1781 | init_completion(&ioc->internal_cmds.done); | ||
| 1782 | mutex_init(&ioc->mptbase_cmds.mutex); | ||
| 1783 | init_completion(&ioc->mptbase_cmds.done); | ||
| 1784 | mutex_init(&ioc->taskmgmt_cmds.mutex); | ||
| 1785 | init_completion(&ioc->taskmgmt_cmds.done); | ||
| 1661 | 1786 | ||
| 1662 | /* Initialize the event logging. | 1787 | /* Initialize the event logging. |
| 1663 | */ | 1788 | */ |
| @@ -1670,16 +1795,13 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1670 | ioc->mfcnt = 0; | 1795 | ioc->mfcnt = 0; |
| 1671 | #endif | 1796 | #endif |
| 1672 | 1797 | ||
| 1798 | ioc->sh = NULL; | ||
| 1673 | ioc->cached_fw = NULL; | 1799 | ioc->cached_fw = NULL; |
| 1674 | 1800 | ||
| 1675 | /* Initilize SCSI Config Data structure | 1801 | /* Initilize SCSI Config Data structure |
| 1676 | */ | 1802 | */ |
| 1677 | memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); | 1803 | memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); |
| 1678 | 1804 | ||
| 1679 | /* Initialize the running configQ head. | ||
| 1680 | */ | ||
| 1681 | INIT_LIST_HEAD(&ioc->configQ); | ||
| 1682 | |||
| 1683 | /* Initialize the fc rport list head. | 1805 | /* Initialize the fc rport list head. |
| 1684 | */ | 1806 | */ |
| 1685 | INIT_LIST_HEAD(&ioc->fc_rports); | 1807 | INIT_LIST_HEAD(&ioc->fc_rports); |
| @@ -1690,9 +1812,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1690 | 1812 | ||
| 1691 | /* Initialize workqueue */ | 1813 | /* Initialize workqueue */ |
| 1692 | INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work); | 1814 | INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work); |
| 1693 | spin_lock_init(&ioc->fault_reset_work_lock); | ||
| 1694 | 1815 | ||
| 1695 | snprintf(ioc->reset_work_q_name, sizeof(ioc->reset_work_q_name), | 1816 | snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN, |
| 1696 | "mpt_poll_%d", ioc->id); | 1817 | "mpt_poll_%d", ioc->id); |
| 1697 | ioc->reset_work_q = | 1818 | ioc->reset_work_q = |
| 1698 | create_singlethread_workqueue(ioc->reset_work_q_name); | 1819 | create_singlethread_workqueue(ioc->reset_work_q_name); |
| @@ -1767,11 +1888,14 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1767 | case MPI_MANUFACTPAGE_DEVID_SAS1064: | 1888 | case MPI_MANUFACTPAGE_DEVID_SAS1064: |
| 1768 | case MPI_MANUFACTPAGE_DEVID_SAS1068: | 1889 | case MPI_MANUFACTPAGE_DEVID_SAS1068: |
| 1769 | ioc->errata_flag_1064 = 1; | 1890 | ioc->errata_flag_1064 = 1; |
| 1891 | ioc->bus_type = SAS; | ||
| 1892 | break; | ||
| 1770 | 1893 | ||
| 1771 | case MPI_MANUFACTPAGE_DEVID_SAS1064E: | 1894 | case MPI_MANUFACTPAGE_DEVID_SAS1064E: |
| 1772 | case MPI_MANUFACTPAGE_DEVID_SAS1068E: | 1895 | case MPI_MANUFACTPAGE_DEVID_SAS1068E: |
| 1773 | case MPI_MANUFACTPAGE_DEVID_SAS1078: | 1896 | case MPI_MANUFACTPAGE_DEVID_SAS1078: |
| 1774 | ioc->bus_type = SAS; | 1897 | ioc->bus_type = SAS; |
| 1898 | break; | ||
| 1775 | } | 1899 | } |
| 1776 | 1900 | ||
| 1777 | 1901 | ||
| @@ -1813,6 +1937,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1813 | */ | 1937 | */ |
| 1814 | mpt_detect_bound_ports(ioc, pdev); | 1938 | mpt_detect_bound_ports(ioc, pdev); |
| 1815 | 1939 | ||
| 1940 | INIT_LIST_HEAD(&ioc->fw_event_list); | ||
| 1941 | spin_lock_init(&ioc->fw_event_lock); | ||
| 1942 | snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id); | ||
| 1943 | ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name); | ||
| 1944 | |||
| 1816 | if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, | 1945 | if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, |
| 1817 | CAN_SLEEP)) != 0){ | 1946 | CAN_SLEEP)) != 0){ |
| 1818 | printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n", | 1947 | printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n", |
| @@ -1885,13 +2014,18 @@ mpt_detach(struct pci_dev *pdev) | |||
| 1885 | /* | 2014 | /* |
| 1886 | * Stop polling ioc for fault condition | 2015 | * Stop polling ioc for fault condition |
| 1887 | */ | 2016 | */ |
| 1888 | spin_lock_irqsave(&ioc->fault_reset_work_lock, flags); | 2017 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
| 1889 | wq = ioc->reset_work_q; | 2018 | wq = ioc->reset_work_q; |
| 1890 | ioc->reset_work_q = NULL; | 2019 | ioc->reset_work_q = NULL; |
| 1891 | spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags); | 2020 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); |
| 1892 | cancel_delayed_work(&ioc->fault_reset_work); | 2021 | cancel_delayed_work(&ioc->fault_reset_work); |
| 1893 | destroy_workqueue(wq); | 2022 | destroy_workqueue(wq); |
| 1894 | 2023 | ||
| 2024 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 2025 | wq = ioc->fw_event_q; | ||
| 2026 | ioc->fw_event_q = NULL; | ||
| 2027 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 2028 | destroy_workqueue(wq); | ||
| 1895 | 2029 | ||
| 1896 | sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); | 2030 | sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); |
| 1897 | remove_proc_entry(pname, NULL); | 2031 | remove_proc_entry(pname, NULL); |
| @@ -1994,6 +2128,21 @@ mpt_resume(struct pci_dev *pdev) | |||
| 1994 | if (err) | 2128 | if (err) |
| 1995 | return err; | 2129 | return err; |
| 1996 | 2130 | ||
| 2131 | if (ioc->dma_mask == DMA_BIT_MASK(64)) { | ||
| 2132 | if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) | ||
| 2133 | ioc->add_sge = &mpt_add_sge_64bit_1078; | ||
| 2134 | else | ||
| 2135 | ioc->add_sge = &mpt_add_sge_64bit; | ||
| 2136 | ioc->add_chain = &mpt_add_chain_64bit; | ||
| 2137 | ioc->sg_addr_size = 8; | ||
| 2138 | } else { | ||
| 2139 | |||
| 2140 | ioc->add_sge = &mpt_add_sge; | ||
| 2141 | ioc->add_chain = &mpt_add_chain; | ||
| 2142 | ioc->sg_addr_size = 4; | ||
| 2143 | } | ||
| 2144 | ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size; | ||
| 2145 | |||
| 1997 | printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", | 2146 | printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", |
| 1998 | ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT), | 2147 | ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT), |
| 1999 | CHIPREG_READ32(&ioc->chip->Doorbell)); | 2148 | CHIPREG_READ32(&ioc->chip->Doorbell)); |
| @@ -2091,12 +2240,16 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2091 | ioc->active = 0; | 2240 | ioc->active = 0; |
| 2092 | 2241 | ||
| 2093 | if (ioc->alt_ioc) { | 2242 | if (ioc->alt_ioc) { |
| 2094 | if (ioc->alt_ioc->active) | 2243 | if (ioc->alt_ioc->active || |
| 2244 | reason == MPT_HOSTEVENT_IOC_RECOVER) { | ||
| 2095 | reset_alt_ioc_active = 1; | 2245 | reset_alt_ioc_active = 1; |
| 2096 | 2246 | /* Disable alt-IOC's reply interrupts | |
| 2097 | /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */ | 2247 | * (and FreeQ) for a bit |
| 2098 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF); | 2248 | **/ |
| 2099 | ioc->alt_ioc->active = 0; | 2249 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, |
| 2250 | 0xFFFFFFFF); | ||
| 2251 | ioc->alt_ioc->active = 0; | ||
| 2252 | } | ||
| 2100 | } | 2253 | } |
| 2101 | 2254 | ||
| 2102 | hard = 1; | 2255 | hard = 1; |
| @@ -2117,9 +2270,11 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2117 | } | 2270 | } |
| 2118 | 2271 | ||
| 2119 | } else { | 2272 | } else { |
| 2120 | printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name); | 2273 | printk(MYIOC_s_WARN_FMT |
| 2274 | "NOT READY WARNING!\n", ioc->name); | ||
| 2121 | } | 2275 | } |
| 2122 | return -1; | 2276 | ret = -1; |
| 2277 | goto out; | ||
| 2123 | } | 2278 | } |
| 2124 | 2279 | ||
| 2125 | /* hard_reset_done = 0 if a soft reset was performed | 2280 | /* hard_reset_done = 0 if a soft reset was performed |
| @@ -2129,7 +2284,9 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2129 | if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) | 2284 | if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) |
| 2130 | alt_ioc_ready = 1; | 2285 | alt_ioc_ready = 1; |
| 2131 | else | 2286 | else |
| 2132 | printk(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name); | 2287 | printk(MYIOC_s_WARN_FMT |
| 2288 | ": alt-ioc Not ready WARNING!\n", | ||
| 2289 | ioc->alt_ioc->name); | ||
| 2133 | } | 2290 | } |
| 2134 | 2291 | ||
| 2135 | for (ii=0; ii<5; ii++) { | 2292 | for (ii=0; ii<5; ii++) { |
| @@ -2150,7 +2307,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2150 | if (alt_ioc_ready) { | 2307 | if (alt_ioc_ready) { |
| 2151 | if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { | 2308 | if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { |
| 2152 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 2309 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2153 | "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc)); | 2310 | "Initial Alt IocFacts failed rc=%x\n", |
| 2311 | ioc->name, rc)); | ||
| 2154 | /* Retry - alt IOC was initialized once | 2312 | /* Retry - alt IOC was initialized once |
| 2155 | */ | 2313 | */ |
| 2156 | rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); | 2314 | rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); |
| @@ -2194,16 +2352,20 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2194 | IRQF_SHARED, ioc->name, ioc); | 2352 | IRQF_SHARED, ioc->name, ioc); |
| 2195 | if (rc < 0) { | 2353 | if (rc < 0) { |
| 2196 | printk(MYIOC_s_ERR_FMT "Unable to allocate " | 2354 | printk(MYIOC_s_ERR_FMT "Unable to allocate " |
| 2197 | "interrupt %d!\n", ioc->name, ioc->pcidev->irq); | 2355 | "interrupt %d!\n", |
| 2356 | ioc->name, ioc->pcidev->irq); | ||
| 2198 | if (ioc->msi_enable) | 2357 | if (ioc->msi_enable) |
| 2199 | pci_disable_msi(ioc->pcidev); | 2358 | pci_disable_msi(ioc->pcidev); |
| 2200 | return -EBUSY; | 2359 | ret = -EBUSY; |
| 2360 | goto out; | ||
| 2201 | } | 2361 | } |
| 2202 | irq_allocated = 1; | 2362 | irq_allocated = 1; |
| 2203 | ioc->pci_irq = ioc->pcidev->irq; | 2363 | ioc->pci_irq = ioc->pcidev->irq; |
| 2204 | pci_set_master(ioc->pcidev); /* ?? */ | 2364 | pci_set_master(ioc->pcidev); /* ?? */ |
| 2205 | dprintk(ioc, printk(MYIOC_s_INFO_FMT "installed at interrupt " | 2365 | pci_set_drvdata(ioc->pcidev, ioc); |
| 2206 | "%d\n", ioc->name, ioc->pcidev->irq)); | 2366 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT |
| 2367 | "installed at interrupt %d\n", ioc->name, | ||
| 2368 | ioc->pcidev->irq)); | ||
| 2207 | } | 2369 | } |
| 2208 | } | 2370 | } |
| 2209 | 2371 | ||
| @@ -2212,17 +2374,22 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2212 | * init as upper addresses are needed for init. | 2374 | * init as upper addresses are needed for init. |
| 2213 | * If fails, continue with alt-ioc processing | 2375 | * If fails, continue with alt-ioc processing |
| 2214 | */ | 2376 | */ |
| 2377 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "PrimeIocFifos\n", | ||
| 2378 | ioc->name)); | ||
| 2215 | if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0)) | 2379 | if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0)) |
| 2216 | ret = -3; | 2380 | ret = -3; |
| 2217 | 2381 | ||
| 2218 | /* May need to check/upload firmware & data here! | 2382 | /* May need to check/upload firmware & data here! |
| 2219 | * If fails, continue with alt-ioc processing | 2383 | * If fails, continue with alt-ioc processing |
| 2220 | */ | 2384 | */ |
| 2385 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "SendIocInit\n", | ||
| 2386 | ioc->name)); | ||
| 2221 | if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0)) | 2387 | if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0)) |
| 2222 | ret = -4; | 2388 | ret = -4; |
| 2223 | // NEW! | 2389 | // NEW! |
| 2224 | if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) { | 2390 | if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) { |
| 2225 | printk(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n", | 2391 | printk(MYIOC_s_WARN_FMT |
| 2392 | ": alt-ioc (%d) FIFO mgmt alloc WARNING!\n", | ||
| 2226 | ioc->alt_ioc->name, rc); | 2393 | ioc->alt_ioc->name, rc); |
| 2227 | alt_ioc_ready = 0; | 2394 | alt_ioc_ready = 0; |
| 2228 | reset_alt_ioc_active = 0; | 2395 | reset_alt_ioc_active = 0; |
| @@ -2232,8 +2399,9 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2232 | if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { | 2399 | if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { |
| 2233 | alt_ioc_ready = 0; | 2400 | alt_ioc_ready = 0; |
| 2234 | reset_alt_ioc_active = 0; | 2401 | reset_alt_ioc_active = 0; |
| 2235 | printk(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n", | 2402 | printk(MYIOC_s_WARN_FMT |
| 2236 | ioc->alt_ioc->name, rc); | 2403 | ": alt-ioc: (%d) init failure WARNING!\n", |
| 2404 | ioc->alt_ioc->name, rc); | ||
| 2237 | } | 2405 | } |
| 2238 | } | 2406 | } |
| 2239 | 2407 | ||
| @@ -2269,28 +2437,36 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2269 | } | 2437 | } |
| 2270 | } | 2438 | } |
| 2271 | 2439 | ||
| 2440 | /* Enable MPT base driver management of EventNotification | ||
| 2441 | * and EventAck handling. | ||
| 2442 | */ | ||
| 2443 | if ((ret == 0) && (!ioc->facts.EventState)) { | ||
| 2444 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | ||
| 2445 | "SendEventNotification\n", | ||
| 2446 | ioc->name)); | ||
| 2447 | ret = SendEventNotification(ioc, 1, sleepFlag); /* 1=Enable */ | ||
| 2448 | } | ||
| 2449 | |||
| 2450 | if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) | ||
| 2451 | rc = SendEventNotification(ioc->alt_ioc, 1, sleepFlag); | ||
| 2452 | |||
| 2272 | if (ret == 0) { | 2453 | if (ret == 0) { |
| 2273 | /* Enable! (reply interrupt) */ | 2454 | /* Enable! (reply interrupt) */ |
| 2274 | CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); | 2455 | CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); |
| 2275 | ioc->active = 1; | 2456 | ioc->active = 1; |
| 2276 | } | 2457 | } |
| 2277 | 2458 | if (rc == 0) { /* alt ioc */ | |
| 2278 | if (reset_alt_ioc_active && ioc->alt_ioc) { | 2459 | if (reset_alt_ioc_active && ioc->alt_ioc) { |
| 2279 | /* (re)Enable alt-IOC! (reply interrupt) */ | 2460 | /* (re)Enable alt-IOC! (reply interrupt) */ |
| 2280 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n", | 2461 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "alt-ioc" |
| 2281 | ioc->alt_ioc->name)); | 2462 | "reply irq re-enabled\n", |
| 2282 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); | 2463 | ioc->alt_ioc->name)); |
| 2283 | ioc->alt_ioc->active = 1; | 2464 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, |
| 2465 | MPI_HIM_DIM); | ||
| 2466 | ioc->alt_ioc->active = 1; | ||
| 2467 | } | ||
| 2284 | } | 2468 | } |
| 2285 | 2469 | ||
| 2286 | /* Enable MPT base driver management of EventNotification | ||
| 2287 | * and EventAck handling. | ||
| 2288 | */ | ||
| 2289 | if ((ret == 0) && (!ioc->facts.EventState)) | ||
| 2290 | (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */ | ||
| 2291 | |||
| 2292 | if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) | ||
| 2293 | (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */ | ||
| 2294 | 2470 | ||
| 2295 | /* Add additional "reason" check before call to GetLanConfigPages | 2471 | /* Add additional "reason" check before call to GetLanConfigPages |
| 2296 | * (combined with GetIoUnitPage2 call). This prevents a somewhat | 2472 | * (combined with GetIoUnitPage2 call). This prevents a somewhat |
| @@ -2306,8 +2482,9 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2306 | mutex_init(&ioc->raid_data.inactive_list_mutex); | 2482 | mutex_init(&ioc->raid_data.inactive_list_mutex); |
| 2307 | INIT_LIST_HEAD(&ioc->raid_data.inactive_list); | 2483 | INIT_LIST_HEAD(&ioc->raid_data.inactive_list); |
| 2308 | 2484 | ||
| 2309 | if (ioc->bus_type == SAS) { | 2485 | switch (ioc->bus_type) { |
| 2310 | 2486 | ||
| 2487 | case SAS: | ||
| 2311 | /* clear persistency table */ | 2488 | /* clear persistency table */ |
| 2312 | if(ioc->facts.IOCExceptions & | 2489 | if(ioc->facts.IOCExceptions & |
| 2313 | MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) { | 2490 | MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) { |
| @@ -2321,8 +2498,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2321 | */ | 2498 | */ |
| 2322 | mpt_findImVolumes(ioc); | 2499 | mpt_findImVolumes(ioc); |
| 2323 | 2500 | ||
| 2324 | } else if (ioc->bus_type == FC) { | 2501 | /* Check, and possibly reset, the coalescing value |
| 2325 | if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && | 2502 | */ |
| 2503 | mpt_read_ioc_pg_1(ioc); | ||
| 2504 | |||
| 2505 | break; | ||
| 2506 | |||
| 2507 | case FC: | ||
| 2508 | if ((ioc->pfacts[0].ProtocolFlags & | ||
| 2509 | MPI_PORTFACTS_PROTOCOL_LAN) && | ||
| 2326 | (ioc->lan_cnfg_page0.Header.PageLength == 0)) { | 2510 | (ioc->lan_cnfg_page0.Header.PageLength == 0)) { |
| 2327 | /* | 2511 | /* |
| 2328 | * Pre-fetch the ports LAN MAC address! | 2512 | * Pre-fetch the ports LAN MAC address! |
| @@ -2331,11 +2515,14 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2331 | (void) GetLanConfigPages(ioc); | 2515 | (void) GetLanConfigPages(ioc); |
| 2332 | a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; | 2516 | a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; |
| 2333 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 2517 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2334 | "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", | 2518 | "LanAddr = %02X:%02X:%02X" |
| 2335 | ioc->name, a[5], a[4], a[3], a[2], a[1], a[0])); | 2519 | ":%02X:%02X:%02X\n", |
| 2336 | 2520 | ioc->name, a[5], a[4], | |
| 2521 | a[3], a[2], a[1], a[0])); | ||
| 2337 | } | 2522 | } |
| 2338 | } else { | 2523 | break; |
| 2524 | |||
| 2525 | case SPI: | ||
| 2339 | /* Get NVRAM and adapter maximums from SPP 0 and 2 | 2526 | /* Get NVRAM and adapter maximums from SPP 0 and 2 |
| 2340 | */ | 2527 | */ |
| 2341 | mpt_GetScsiPortSettings(ioc, 0); | 2528 | mpt_GetScsiPortSettings(ioc, 0); |
| @@ -2354,6 +2541,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 2354 | mpt_read_ioc_pg_1(ioc); | 2541 | mpt_read_ioc_pg_1(ioc); |
| 2355 | 2542 | ||
| 2356 | mpt_read_ioc_pg_4(ioc); | 2543 | mpt_read_ioc_pg_4(ioc); |
| 2544 | |||
| 2545 | break; | ||
| 2357 | } | 2546 | } |
| 2358 | 2547 | ||
| 2359 | GetIoUnitPage2(ioc); | 2548 | GetIoUnitPage2(ioc); |
| @@ -2435,16 +2624,20 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) | |||
| 2435 | if (_pcidev == peer) { | 2624 | if (_pcidev == peer) { |
| 2436 | /* Paranoia checks */ | 2625 | /* Paranoia checks */ |
| 2437 | if (ioc->alt_ioc != NULL) { | 2626 | if (ioc->alt_ioc != NULL) { |
| 2438 | printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n", | 2627 | printk(MYIOC_s_WARN_FMT |
| 2439 | ioc->name, ioc->alt_ioc->name); | 2628 | "Oops, already bound (%s <==> %s)!\n", |
| 2629 | ioc->name, ioc->name, ioc->alt_ioc->name); | ||
| 2440 | break; | 2630 | break; |
| 2441 | } else if (ioc_srch->alt_ioc != NULL) { | 2631 | } else if (ioc_srch->alt_ioc != NULL) { |
| 2442 | printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n", | 2632 | printk(MYIOC_s_WARN_FMT |
| 2443 | ioc_srch->name, ioc_srch->alt_ioc->name); | 2633 | "Oops, already bound (%s <==> %s)!\n", |
| 2634 | ioc_srch->name, ioc_srch->name, | ||
| 2635 | ioc_srch->alt_ioc->name); | ||
| 2444 | break; | 2636 | break; |
| 2445 | } | 2637 | } |
| 2446 | dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n", | 2638 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2447 | ioc->name, ioc_srch->name)); | 2639 | "FOUND! binding %s <==> %s\n", |
| 2640 | ioc->name, ioc->name, ioc_srch->name)); | ||
| 2448 | ioc_srch->alt_ioc = ioc; | 2641 | ioc_srch->alt_ioc = ioc; |
| 2449 | ioc->alt_ioc = ioc_srch; | 2642 | ioc->alt_ioc = ioc_srch; |
| 2450 | } | 2643 | } |
| @@ -2464,8 +2657,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) | |||
| 2464 | int ret; | 2657 | int ret; |
| 2465 | 2658 | ||
| 2466 | if (ioc->cached_fw != NULL) { | 2659 | if (ioc->cached_fw != NULL) { |
| 2467 | ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto " | 2660 | ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2468 | "adapter\n", __func__, ioc->name)); | 2661 | "%s: Pushing FW onto adapter\n", __func__, ioc->name)); |
| 2469 | if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *) | 2662 | if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *) |
| 2470 | ioc->cached_fw, CAN_SLEEP)) < 0) { | 2663 | ioc->cached_fw, CAN_SLEEP)) < 0) { |
| 2471 | printk(MYIOC_s_WARN_FMT | 2664 | printk(MYIOC_s_WARN_FMT |
| @@ -2474,11 +2667,30 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) | |||
| 2474 | } | 2667 | } |
| 2475 | } | 2668 | } |
| 2476 | 2669 | ||
| 2670 | /* | ||
| 2671 | * Put the controller into ready state (if its not already) | ||
| 2672 | */ | ||
| 2673 | if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) { | ||
| 2674 | if (!SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, | ||
| 2675 | CAN_SLEEP)) { | ||
| 2676 | if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) | ||
| 2677 | printk(MYIOC_s_ERR_FMT "%s: IOC msg unit " | ||
| 2678 | "reset failed to put ioc in ready state!\n", | ||
| 2679 | ioc->name, __func__); | ||
| 2680 | } else | ||
| 2681 | printk(MYIOC_s_ERR_FMT "%s: IOC msg unit reset " | ||
| 2682 | "failed!\n", ioc->name, __func__); | ||
| 2683 | } | ||
| 2684 | |||
| 2685 | |||
| 2477 | /* Disable adapter interrupts! */ | 2686 | /* Disable adapter interrupts! */ |
| 2687 | synchronize_irq(ioc->pcidev->irq); | ||
| 2478 | CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); | 2688 | CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); |
| 2479 | ioc->active = 0; | 2689 | ioc->active = 0; |
| 2690 | |||
| 2480 | /* Clear any lingering interrupt */ | 2691 | /* Clear any lingering interrupt */ |
| 2481 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); | 2692 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); |
| 2693 | CHIPREG_READ32(&ioc->chip->IntStatus); | ||
| 2482 | 2694 | ||
| 2483 | if (ioc->alloc != NULL) { | 2695 | if (ioc->alloc != NULL) { |
| 2484 | sz = ioc->alloc_sz; | 2696 | sz = ioc->alloc_sz; |
| @@ -2538,19 +2750,22 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) | |||
| 2538 | if((ret = mpt_host_page_access_control(ioc, | 2750 | if((ret = mpt_host_page_access_control(ioc, |
| 2539 | MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) { | 2751 | MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) { |
| 2540 | printk(MYIOC_s_ERR_FMT | 2752 | printk(MYIOC_s_ERR_FMT |
| 2541 | "host page buffers free failed (%d)!\n", | 2753 | ": %s: host page buffers free failed (%d)!\n", |
| 2542 | ioc->name, ret); | 2754 | ioc->name, __func__, ret); |
| 2543 | } | 2755 | } |
| 2544 | dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free @ %p, sz=%d bytes\n", | 2756 | dexitprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2545 | ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz)); | 2757 | "HostPageBuffer free @ %p, sz=%d bytes\n", |
| 2758 | ioc->name, ioc->HostPageBuffer, | ||
| 2759 | ioc->HostPageBuffer_sz)); | ||
| 2546 | pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz, | 2760 | pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz, |
| 2547 | ioc->HostPageBuffer, ioc->HostPageBuffer_dma); | 2761 | ioc->HostPageBuffer, ioc->HostPageBuffer_dma); |
| 2548 | ioc->HostPageBuffer = NULL; | 2762 | ioc->HostPageBuffer = NULL; |
| 2549 | ioc->HostPageBuffer_sz = 0; | 2763 | ioc->HostPageBuffer_sz = 0; |
| 2550 | ioc->alloc_total -= ioc->HostPageBuffer_sz; | 2764 | ioc->alloc_total -= ioc->HostPageBuffer_sz; |
| 2551 | } | 2765 | } |
| 2552 | } | ||
| 2553 | 2766 | ||
| 2767 | pci_set_drvdata(ioc->pcidev, NULL); | ||
| 2768 | } | ||
| 2554 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2769 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 2555 | /** | 2770 | /** |
| 2556 | * mpt_adapter_dispose - Free all resources associated with an MPT adapter | 2771 | * mpt_adapter_dispose - Free all resources associated with an MPT adapter |
| @@ -2690,8 +2905,12 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) | |||
| 2690 | } | 2905 | } |
| 2691 | 2906 | ||
| 2692 | /* Is it already READY? */ | 2907 | /* Is it already READY? */ |
| 2693 | if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) | 2908 | if (!statefault && |
| 2909 | ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)) { | ||
| 2910 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | ||
| 2911 | "IOC is in READY state\n", ioc->name)); | ||
| 2694 | return 0; | 2912 | return 0; |
| 2913 | } | ||
| 2695 | 2914 | ||
| 2696 | /* | 2915 | /* |
| 2697 | * Check to see if IOC is in FAULT state. | 2916 | * Check to see if IOC is in FAULT state. |
| @@ -2764,8 +2983,9 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) | |||
| 2764 | 2983 | ||
| 2765 | ii++; cntdn--; | 2984 | ii++; cntdn--; |
| 2766 | if (!cntdn) { | 2985 | if (!cntdn) { |
| 2767 | printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n", | 2986 | printk(MYIOC_s_ERR_FMT |
| 2768 | ioc->name, (int)((ii+5)/HZ)); | 2987 | "Wait IOC_READY state (0x%x) timeout(%d)!\n", |
| 2988 | ioc->name, ioc_state, (int)((ii+5)/HZ)); | ||
| 2769 | return -ETIME; | 2989 | return -ETIME; |
| 2770 | } | 2990 | } |
| 2771 | 2991 | ||
| @@ -2778,9 +2998,8 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) | |||
| 2778 | } | 2998 | } |
| 2779 | 2999 | ||
| 2780 | if (statefault < 3) { | 3000 | if (statefault < 3) { |
| 2781 | printk(MYIOC_s_INFO_FMT "Recovered from %s\n", | 3001 | printk(MYIOC_s_INFO_FMT "Recovered from %s\n", ioc->name, |
| 2782 | ioc->name, | 3002 | statefault == 1 ? "stuck handshake" : "IOC FAULT"); |
| 2783 | statefault==1 ? "stuck handshake" : "IOC FAULT"); | ||
| 2784 | } | 3003 | } |
| 2785 | 3004 | ||
| 2786 | return hard_reset_done; | 3005 | return hard_reset_done; |
| @@ -2833,8 +3052,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) | |||
| 2833 | 3052 | ||
| 2834 | /* IOC *must* NOT be in RESET state! */ | 3053 | /* IOC *must* NOT be in RESET state! */ |
| 2835 | if (ioc->last_state == MPI_IOC_STATE_RESET) { | 3054 | if (ioc->last_state == MPI_IOC_STATE_RESET) { |
| 2836 | printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n", | 3055 | printk(KERN_ERR MYNAM |
| 2837 | ioc->name, ioc->last_state ); | 3056 | ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n", |
| 3057 | ioc->name, ioc->last_state); | ||
| 2838 | return -44; | 3058 | return -44; |
| 2839 | } | 3059 | } |
| 2840 | 3060 | ||
| @@ -2896,7 +3116,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) | |||
| 2896 | * Old: u16{Major(4),Minor(4),SubMinor(8)} | 3116 | * Old: u16{Major(4),Minor(4),SubMinor(8)} |
| 2897 | * New: u32{Major(8),Minor(8),Unit(8),Dev(8)} | 3117 | * New: u32{Major(8),Minor(8),Unit(8),Dev(8)} |
| 2898 | */ | 3118 | */ |
| 2899 | if (facts->MsgVersion < 0x0102) { | 3119 | if (facts->MsgVersion < MPI_VERSION_01_02) { |
| 2900 | /* | 3120 | /* |
| 2901 | * Handle old FC f/w style, convert to new... | 3121 | * Handle old FC f/w style, convert to new... |
| 2902 | */ | 3122 | */ |
| @@ -2908,9 +3128,11 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) | |||
| 2908 | facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); | 3128 | facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); |
| 2909 | 3129 | ||
| 2910 | facts->ProductID = le16_to_cpu(facts->ProductID); | 3130 | facts->ProductID = le16_to_cpu(facts->ProductID); |
| 3131 | |||
| 2911 | if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) | 3132 | if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) |
| 2912 | > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) | 3133 | > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) |
| 2913 | ioc->ir_firmware = 1; | 3134 | ioc->ir_firmware = 1; |
| 3135 | |||
| 2914 | facts->CurrentHostMfaHighAddr = | 3136 | facts->CurrentHostMfaHighAddr = |
| 2915 | le32_to_cpu(facts->CurrentHostMfaHighAddr); | 3137 | le32_to_cpu(facts->CurrentHostMfaHighAddr); |
| 2916 | facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); | 3138 | facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); |
| @@ -2926,7 +3148,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) | |||
| 2926 | * to 14 in MPI-1.01.0x. | 3148 | * to 14 in MPI-1.01.0x. |
| 2927 | */ | 3149 | */ |
| 2928 | if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 && | 3150 | if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 && |
| 2929 | facts->MsgVersion > 0x0100) { | 3151 | facts->MsgVersion > MPI_VERSION_01_00) { |
| 2930 | facts->FWImageSize = le32_to_cpu(facts->FWImageSize); | 3152 | facts->FWImageSize = le32_to_cpu(facts->FWImageSize); |
| 2931 | } | 3153 | } |
| 2932 | 3154 | ||
| @@ -3108,6 +3330,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) | |||
| 3108 | 3330 | ||
| 3109 | ioc_init.MaxDevices = (U8)ioc->devices_per_bus; | 3331 | ioc_init.MaxDevices = (U8)ioc->devices_per_bus; |
| 3110 | ioc_init.MaxBuses = (U8)ioc->number_of_buses; | 3332 | ioc_init.MaxBuses = (U8)ioc->number_of_buses; |
| 3333 | |||
| 3111 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n", | 3334 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n", |
| 3112 | ioc->name, ioc->facts.MsgVersion)); | 3335 | ioc->name, ioc->facts.MsgVersion)); |
| 3113 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { | 3336 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { |
| @@ -3122,7 +3345,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) | |||
| 3122 | } | 3345 | } |
| 3123 | ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ | 3346 | ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ |
| 3124 | 3347 | ||
| 3125 | if (sizeof(dma_addr_t) == sizeof(u64)) { | 3348 | if (ioc->sg_addr_size == sizeof(u64)) { |
| 3126 | /* Save the upper 32-bits of the request | 3349 | /* Save the upper 32-bits of the request |
| 3127 | * (reply) and sense buffers. | 3350 | * (reply) and sense buffers. |
| 3128 | */ | 3351 | */ |
| @@ -3325,11 +3548,10 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) | |||
| 3325 | FWUpload_t *prequest; | 3548 | FWUpload_t *prequest; |
| 3326 | FWUploadReply_t *preply; | 3549 | FWUploadReply_t *preply; |
| 3327 | FWUploadTCSGE_t *ptcsge; | 3550 | FWUploadTCSGE_t *ptcsge; |
| 3328 | int sgeoffset; | ||
| 3329 | u32 flagsLength; | 3551 | u32 flagsLength; |
| 3330 | int ii, sz, reply_sz; | 3552 | int ii, sz, reply_sz; |
| 3331 | int cmdStatus; | 3553 | int cmdStatus; |
| 3332 | 3554 | int request_size; | |
| 3333 | /* If the image size is 0, we are done. | 3555 | /* If the image size is 0, we are done. |
| 3334 | */ | 3556 | */ |
| 3335 | if ((sz = ioc->facts.FWImageSize) == 0) | 3557 | if ((sz = ioc->facts.FWImageSize) == 0) |
| @@ -3364,42 +3586,41 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) | |||
| 3364 | ptcsge->ImageSize = cpu_to_le32(sz); | 3586 | ptcsge->ImageSize = cpu_to_le32(sz); |
| 3365 | ptcsge++; | 3587 | ptcsge++; |
| 3366 | 3588 | ||
| 3367 | sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t); | ||
| 3368 | |||
| 3369 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz; | 3589 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz; |
| 3370 | mpt_add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma); | 3590 | ioc->add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma); |
| 3371 | 3591 | request_size = offsetof(FWUpload_t, SGL) + sizeof(FWUploadTCSGE_t) + | |
| 3372 | sgeoffset += sizeof(u32) + sizeof(dma_addr_t); | 3592 | ioc->SGE_size; |
| 3373 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": Sending FW Upload (req @ %p) sgeoffset=%d \n", | 3593 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending FW Upload " |
| 3374 | ioc->name, prequest, sgeoffset)); | 3594 | " (req @ %p) fw_size=%d mf_request_size=%d\n", ioc->name, prequest, |
| 3595 | ioc->facts.FWImageSize, request_size)); | ||
| 3375 | DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest); | 3596 | DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest); |
| 3376 | 3597 | ||
| 3377 | ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest, | 3598 | ii = mpt_handshake_req_reply_wait(ioc, request_size, (u32 *)prequest, |
| 3378 | reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag); | 3599 | reply_sz, (u16 *)preply, 65 /*seconds*/, sleepFlag); |
| 3379 | 3600 | ||
| 3380 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii)); | 3601 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Upload completed " |
| 3602 | "rc=%x \n", ioc->name, ii)); | ||
| 3381 | 3603 | ||
| 3382 | cmdStatus = -EFAULT; | 3604 | cmdStatus = -EFAULT; |
| 3383 | if (ii == 0) { | 3605 | if (ii == 0) { |
| 3384 | /* Handshake transfer was complete and successful. | 3606 | /* Handshake transfer was complete and successful. |
| 3385 | * Check the Reply Frame. | 3607 | * Check the Reply Frame. |
| 3386 | */ | 3608 | */ |
| 3387 | int status, transfer_sz; | 3609 | int status; |
| 3388 | status = le16_to_cpu(preply->IOCStatus); | 3610 | status = le16_to_cpu(preply->IOCStatus) & |
| 3389 | if (status == MPI_IOCSTATUS_SUCCESS) { | 3611 | MPI_IOCSTATUS_MASK; |
| 3390 | transfer_sz = le32_to_cpu(preply->ActualImageSize); | 3612 | if (status == MPI_IOCSTATUS_SUCCESS && |
| 3391 | if (transfer_sz == sz) | 3613 | ioc->facts.FWImageSize == |
| 3614 | le32_to_cpu(preply->ActualImageSize)) | ||
| 3392 | cmdStatus = 0; | 3615 | cmdStatus = 0; |
| 3393 | } | ||
| 3394 | } | 3616 | } |
| 3395 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n", | 3617 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n", |
| 3396 | ioc->name, cmdStatus)); | 3618 | ioc->name, cmdStatus)); |
| 3397 | 3619 | ||
| 3398 | 3620 | ||
| 3399 | if (cmdStatus) { | 3621 | if (cmdStatus) { |
| 3400 | 3622 | ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed, " | |
| 3401 | ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": fw upload failed, freeing image \n", | 3623 | "freeing image \n", ioc->name)); |
| 3402 | ioc->name)); | ||
| 3403 | mpt_free_fw_memory(ioc); | 3624 | mpt_free_fw_memory(ioc); |
| 3404 | } | 3625 | } |
| 3405 | kfree(prequest); | 3626 | kfree(prequest); |
| @@ -3723,6 +3944,10 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
| 3723 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); | 3944 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); |
| 3724 | 3945 | ||
| 3725 | if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { | 3946 | if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { |
| 3947 | |||
| 3948 | if (!ignore) | ||
| 3949 | return 0; | ||
| 3950 | |||
| 3726 | drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " | 3951 | drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " |
| 3727 | "address=%p\n", ioc->name, __func__, | 3952 | "address=%p\n", ioc->name, __func__, |
| 3728 | &ioc->chip->Doorbell, &ioc->chip->Reset_1078)); | 3953 | &ioc->chip->Doorbell, &ioc->chip->Reset_1078)); |
| @@ -3740,6 +3965,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
| 3740 | "looking for READY STATE: doorbell=%x" | 3965 | "looking for READY STATE: doorbell=%x" |
| 3741 | " count=%d\n", | 3966 | " count=%d\n", |
| 3742 | ioc->name, doorbell, count)); | 3967 | ioc->name, doorbell, count)); |
| 3968 | |||
| 3743 | if (doorbell == MPI_IOC_STATE_READY) { | 3969 | if (doorbell == MPI_IOC_STATE_READY) { |
| 3744 | return 1; | 3970 | return 1; |
| 3745 | } | 3971 | } |
| @@ -3890,6 +4116,10 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
| 3890 | doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); | 4116 | doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); |
| 3891 | doorbell &= MPI_IOC_STATE_MASK; | 4117 | doorbell &= MPI_IOC_STATE_MASK; |
| 3892 | 4118 | ||
| 4119 | drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 4120 | "looking for READY STATE: doorbell=%x" | ||
| 4121 | " count=%d\n", ioc->name, doorbell, count)); | ||
| 4122 | |||
| 3893 | if (doorbell == MPI_IOC_STATE_READY) { | 4123 | if (doorbell == MPI_IOC_STATE_READY) { |
| 3894 | break; | 4124 | break; |
| 3895 | } | 4125 | } |
| @@ -3901,6 +4131,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
| 3901 | mdelay (1000); | 4131 | mdelay (1000); |
| 3902 | } | 4132 | } |
| 3903 | } | 4133 | } |
| 4134 | |||
| 4135 | if (doorbell != MPI_IOC_STATE_READY) | ||
| 4136 | printk(MYIOC_s_ERR_FMT "Failed to come READY " | ||
| 4137 | "after reset! IocState=%x", ioc->name, | ||
| 4138 | doorbell); | ||
| 3904 | } | 4139 | } |
| 3905 | } | 4140 | } |
| 3906 | 4141 | ||
| @@ -4019,8 +4254,9 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) | |||
| 4019 | if (sleepFlag != CAN_SLEEP) | 4254 | if (sleepFlag != CAN_SLEEP) |
| 4020 | count *= 10; | 4255 | count *= 10; |
| 4021 | 4256 | ||
| 4022 | printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n", | 4257 | printk(MYIOC_s_ERR_FMT |
| 4023 | ioc->name, (int)((count+5)/HZ)); | 4258 | "Wait IOC_READY state (0x%x) timeout(%d)!\n", |
| 4259 | ioc->name, state, (int)((count+5)/HZ)); | ||
| 4024 | return -ETIME; | 4260 | return -ETIME; |
| 4025 | } | 4261 | } |
| 4026 | 4262 | ||
| @@ -4090,24 +4326,29 @@ initChainBuffers(MPT_ADAPTER *ioc) | |||
| 4090 | * num_sge = num sge in request frame + last chain buffer | 4326 | * num_sge = num sge in request frame + last chain buffer |
| 4091 | * scale = num sge per chain buffer if no chain element | 4327 | * scale = num sge per chain buffer if no chain element |
| 4092 | */ | 4328 | */ |
| 4093 | scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); | 4329 | scale = ioc->req_sz / ioc->SGE_size; |
| 4094 | if (sizeof(dma_addr_t) == sizeof(u64)) | 4330 | if (ioc->sg_addr_size == sizeof(u64)) |
| 4095 | num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32)); | 4331 | num_sge = scale + (ioc->req_sz - 60) / ioc->SGE_size; |
| 4096 | else | 4332 | else |
| 4097 | num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); | 4333 | num_sge = 1 + scale + (ioc->req_sz - 64) / ioc->SGE_size; |
| 4098 | 4334 | ||
| 4099 | if (sizeof(dma_addr_t) == sizeof(u64)) { | 4335 | if (ioc->sg_addr_size == sizeof(u64)) { |
| 4100 | numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + | 4336 | numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + |
| 4101 | (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32)); | 4337 | (ioc->req_sz - 60) / ioc->SGE_size; |
| 4102 | } else { | 4338 | } else { |
| 4103 | numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + | 4339 | numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + |
| 4104 | (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); | 4340 | scale + (ioc->req_sz - 64) / ioc->SGE_size; |
| 4105 | } | 4341 | } |
| 4106 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n", | 4342 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n", |
| 4107 | ioc->name, num_sge, numSGE)); | 4343 | ioc->name, num_sge, numSGE)); |
| 4108 | 4344 | ||
| 4109 | if ( numSGE > MPT_SCSI_SG_DEPTH ) | 4345 | if (ioc->bus_type == FC) { |
| 4110 | numSGE = MPT_SCSI_SG_DEPTH; | 4346 | if (numSGE > MPT_SCSI_FC_SG_DEPTH) |
| 4347 | numSGE = MPT_SCSI_FC_SG_DEPTH; | ||
| 4348 | } else { | ||
| 4349 | if (numSGE > MPT_SCSI_SG_DEPTH) | ||
| 4350 | numSGE = MPT_SCSI_SG_DEPTH; | ||
| 4351 | } | ||
| 4111 | 4352 | ||
| 4112 | num_chain = 1; | 4353 | num_chain = 1; |
| 4113 | while (numSGE - num_sge > 0) { | 4354 | while (numSGE - num_sge > 0) { |
| @@ -4161,12 +4402,42 @@ PrimeIocFifos(MPT_ADAPTER *ioc) | |||
| 4161 | dma_addr_t alloc_dma; | 4402 | dma_addr_t alloc_dma; |
| 4162 | u8 *mem; | 4403 | u8 *mem; |
| 4163 | int i, reply_sz, sz, total_size, num_chain; | 4404 | int i, reply_sz, sz, total_size, num_chain; |
| 4405 | u64 dma_mask; | ||
| 4406 | |||
| 4407 | dma_mask = 0; | ||
| 4164 | 4408 | ||
| 4165 | /* Prime reply FIFO... */ | 4409 | /* Prime reply FIFO... */ |
| 4166 | 4410 | ||
| 4167 | if (ioc->reply_frames == NULL) { | 4411 | if (ioc->reply_frames == NULL) { |
| 4168 | if ( (num_chain = initChainBuffers(ioc)) < 0) | 4412 | if ( (num_chain = initChainBuffers(ioc)) < 0) |
| 4169 | return -1; | 4413 | return -1; |
| 4414 | /* | ||
| 4415 | * 1078 errata workaround for the 36GB limitation | ||
| 4416 | */ | ||
| 4417 | if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078 && | ||
| 4418 | ioc->dma_mask > DMA_35BIT_MASK) { | ||
| 4419 | if (!pci_set_dma_mask(ioc->pcidev, DMA_BIT_MASK(32)) | ||
| 4420 | && !pci_set_consistent_dma_mask(ioc->pcidev, | ||
| 4421 | DMA_BIT_MASK(32))) { | ||
| 4422 | dma_mask = DMA_35BIT_MASK; | ||
| 4423 | d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 4424 | "setting 35 bit addressing for " | ||
| 4425 | "Request/Reply/Chain and Sense Buffers\n", | ||
| 4426 | ioc->name)); | ||
| 4427 | } else { | ||
| 4428 | /*Reseting DMA mask to 64 bit*/ | ||
| 4429 | pci_set_dma_mask(ioc->pcidev, | ||
| 4430 | DMA_BIT_MASK(64)); | ||
| 4431 | pci_set_consistent_dma_mask(ioc->pcidev, | ||
| 4432 | DMA_BIT_MASK(64)); | ||
| 4433 | |||
| 4434 | printk(MYIOC_s_ERR_FMT | ||
| 4435 | "failed setting 35 bit addressing for " | ||
| 4436 | "Request/Reply/Chain and Sense Buffers\n", | ||
| 4437 | ioc->name); | ||
| 4438 | return -1; | ||
| 4439 | } | ||
| 4440 | } | ||
| 4170 | 4441 | ||
| 4171 | total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth); | 4442 | total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth); |
| 4172 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n", | 4443 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n", |
| @@ -4305,9 +4576,16 @@ PrimeIocFifos(MPT_ADAPTER *ioc) | |||
| 4305 | alloc_dma += ioc->reply_sz; | 4576 | alloc_dma += ioc->reply_sz; |
| 4306 | } | 4577 | } |
| 4307 | 4578 | ||
| 4579 | if (dma_mask == DMA_35BIT_MASK && !pci_set_dma_mask(ioc->pcidev, | ||
| 4580 | ioc->dma_mask) && !pci_set_consistent_dma_mask(ioc->pcidev, | ||
| 4581 | ioc->dma_mask)) | ||
| 4582 | d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 4583 | "restoring 64 bit addressing\n", ioc->name)); | ||
| 4584 | |||
| 4308 | return 0; | 4585 | return 0; |
| 4309 | 4586 | ||
| 4310 | out_fail: | 4587 | out_fail: |
| 4588 | |||
| 4311 | if (ioc->alloc != NULL) { | 4589 | if (ioc->alloc != NULL) { |
| 4312 | sz = ioc->alloc_sz; | 4590 | sz = ioc->alloc_sz; |
| 4313 | pci_free_consistent(ioc->pcidev, | 4591 | pci_free_consistent(ioc->pcidev, |
| @@ -4324,6 +4602,13 @@ out_fail: | |||
| 4324 | ioc->sense_buf_pool, ioc->sense_buf_pool_dma); | 4602 | ioc->sense_buf_pool, ioc->sense_buf_pool_dma); |
| 4325 | ioc->sense_buf_pool = NULL; | 4603 | ioc->sense_buf_pool = NULL; |
| 4326 | } | 4604 | } |
| 4605 | |||
| 4606 | if (dma_mask == DMA_35BIT_MASK && !pci_set_dma_mask(ioc->pcidev, | ||
| 4607 | DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(ioc->pcidev, | ||
| 4608 | DMA_BIT_MASK(64))) | ||
| 4609 | d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 4610 | "restoring 64 bit addressing\n", ioc->name)); | ||
| 4611 | |||
| 4327 | return -1; | 4612 | return -1; |
| 4328 | } | 4613 | } |
| 4329 | 4614 | ||
| @@ -4759,7 +5044,14 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) | |||
| 4759 | SasIoUnitControlReply_t *sasIoUnitCntrReply; | 5044 | SasIoUnitControlReply_t *sasIoUnitCntrReply; |
| 4760 | MPT_FRAME_HDR *mf = NULL; | 5045 | MPT_FRAME_HDR *mf = NULL; |
| 4761 | MPIHeader_t *mpi_hdr; | 5046 | MPIHeader_t *mpi_hdr; |
| 5047 | int ret = 0; | ||
| 5048 | unsigned long timeleft; | ||
| 5049 | |||
| 5050 | mutex_lock(&ioc->mptbase_cmds.mutex); | ||
| 4762 | 5051 | ||
| 5052 | /* init the internal cmd struct */ | ||
| 5053 | memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE); | ||
| 5054 | INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status) | ||
| 4763 | 5055 | ||
| 4764 | /* insure garbage is not sent to fw */ | 5056 | /* insure garbage is not sent to fw */ |
| 4765 | switch(persist_opcode) { | 5057 | switch(persist_opcode) { |
| @@ -4769,17 +5061,19 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) | |||
| 4769 | break; | 5061 | break; |
| 4770 | 5062 | ||
| 4771 | default: | 5063 | default: |
| 4772 | return -1; | 5064 | ret = -1; |
| 4773 | break; | 5065 | goto out; |
| 4774 | } | 5066 | } |
| 4775 | 5067 | ||
| 4776 | printk("%s: persist_opcode=%x\n",__func__, persist_opcode); | 5068 | printk(KERN_DEBUG "%s: persist_opcode=%x\n", |
| 5069 | __func__, persist_opcode); | ||
| 4777 | 5070 | ||
| 4778 | /* Get a MF for this command. | 5071 | /* Get a MF for this command. |
| 4779 | */ | 5072 | */ |
| 4780 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { | 5073 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { |
| 4781 | printk("%s: no msg frames!\n",__func__); | 5074 | printk(KERN_DEBUG "%s: no msg frames!\n", __func__); |
| 4782 | return -1; | 5075 | ret = -1; |
| 5076 | goto out; | ||
| 4783 | } | 5077 | } |
| 4784 | 5078 | ||
| 4785 | mpi_hdr = (MPIHeader_t *) mf; | 5079 | mpi_hdr = (MPIHeader_t *) mf; |
| @@ -4789,27 +5083,42 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) | |||
| 4789 | sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; | 5083 | sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; |
| 4790 | sasIoUnitCntrReq->Operation = persist_opcode; | 5084 | sasIoUnitCntrReq->Operation = persist_opcode; |
| 4791 | 5085 | ||
| 4792 | init_timer(&ioc->persist_timer); | ||
| 4793 | ioc->persist_timer.data = (unsigned long) ioc; | ||
| 4794 | ioc->persist_timer.function = mpt_timer_expired; | ||
| 4795 | ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */; | ||
| 4796 | ioc->persist_wait_done=0; | ||
| 4797 | add_timer(&ioc->persist_timer); | ||
| 4798 | mpt_put_msg_frame(mpt_base_index, ioc, mf); | 5086 | mpt_put_msg_frame(mpt_base_index, ioc, mf); |
| 4799 | wait_event(mpt_waitq, ioc->persist_wait_done); | 5087 | timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, 10*HZ); |
| 5088 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | ||
| 5089 | ret = -ETIME; | ||
| 5090 | printk(KERN_DEBUG "%s: failed\n", __func__); | ||
| 5091 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) | ||
| 5092 | goto out; | ||
| 5093 | if (!timeleft) { | ||
| 5094 | printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n", | ||
| 5095 | ioc->name, __func__); | ||
| 5096 | mpt_HardResetHandler(ioc, CAN_SLEEP); | ||
| 5097 | mpt_free_msg_frame(ioc, mf); | ||
| 5098 | } | ||
| 5099 | goto out; | ||
| 5100 | } | ||
| 5101 | |||
| 5102 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { | ||
| 5103 | ret = -1; | ||
| 5104 | goto out; | ||
| 5105 | } | ||
| 4800 | 5106 | ||
| 4801 | sasIoUnitCntrReply = | 5107 | sasIoUnitCntrReply = |
| 4802 | (SasIoUnitControlReply_t *)ioc->persist_reply_frame; | 5108 | (SasIoUnitControlReply_t *)ioc->mptbase_cmds.reply; |
| 4803 | if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) { | 5109 | if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) { |
| 4804 | printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", | 5110 | printk(KERN_DEBUG "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", |
| 4805 | __func__, | 5111 | __func__, sasIoUnitCntrReply->IOCStatus, |
| 4806 | sasIoUnitCntrReply->IOCStatus, | ||
| 4807 | sasIoUnitCntrReply->IOCLogInfo); | 5112 | sasIoUnitCntrReply->IOCLogInfo); |
| 4808 | return -1; | 5113 | printk(KERN_DEBUG "%s: failed\n", __func__); |
| 4809 | } | 5114 | ret = -1; |
| 5115 | } else | ||
| 5116 | printk(KERN_DEBUG "%s: success\n", __func__); | ||
| 5117 | out: | ||
| 4810 | 5118 | ||
| 4811 | printk("%s: success\n",__func__); | 5119 | CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status) |
| 4812 | return 0; | 5120 | mutex_unlock(&ioc->mptbase_cmds.mutex); |
| 5121 | return ret; | ||
| 4813 | } | 5122 | } |
| 4814 | 5123 | ||
| 4815 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 5124 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| @@ -5394,17 +5703,20 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 5394 | * -ENOMEM if pci_alloc failed | 5703 | * -ENOMEM if pci_alloc failed |
| 5395 | **/ | 5704 | **/ |
| 5396 | int | 5705 | int |
| 5397 | mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk) | 5706 | mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, |
| 5707 | RaidPhysDiskPage0_t *phys_disk) | ||
| 5398 | { | 5708 | { |
| 5399 | CONFIGPARMS cfg; | 5709 | CONFIGPARMS cfg; |
| 5400 | ConfigPageHeader_t hdr; | 5710 | ConfigPageHeader_t hdr; |
| 5401 | dma_addr_t dma_handle; | 5711 | dma_addr_t dma_handle; |
| 5402 | pRaidPhysDiskPage0_t buffer = NULL; | 5712 | pRaidPhysDiskPage0_t buffer = NULL; |
| 5403 | int rc; | 5713 | int rc; |
| 5404 | 5714 | ||
| 5405 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | 5715 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); |
| 5406 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | 5716 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); |
| 5717 | memset(phys_disk, 0, sizeof(RaidPhysDiskPage0_t)); | ||
| 5407 | 5718 | ||
| 5719 | hdr.PageVersion = MPI_RAIDPHYSDISKPAGE0_PAGEVERSION; | ||
| 5408 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; | 5720 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; |
| 5409 | cfg.cfghdr.hdr = &hdr; | 5721 | cfg.cfghdr.hdr = &hdr; |
| 5410 | cfg.physAddr = -1; | 5722 | cfg.physAddr = -1; |
| @@ -5451,6 +5763,161 @@ mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t | |||
| 5451 | } | 5763 | } |
| 5452 | 5764 | ||
| 5453 | /** | 5765 | /** |
| 5766 | * mpt_raid_phys_disk_get_num_paths - returns number paths associated to this phys_num | ||
| 5767 | * @ioc: Pointer to a Adapter Structure | ||
| 5768 | * @phys_disk_num: io unit unique phys disk num generated by the ioc | ||
| 5769 | * | ||
| 5770 | * Return: | ||
| 5771 | * returns number paths | ||
| 5772 | **/ | ||
| 5773 | int | ||
| 5774 | mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num) | ||
| 5775 | { | ||
| 5776 | CONFIGPARMS cfg; | ||
| 5777 | ConfigPageHeader_t hdr; | ||
| 5778 | dma_addr_t dma_handle; | ||
| 5779 | pRaidPhysDiskPage1_t buffer = NULL; | ||
| 5780 | int rc; | ||
| 5781 | |||
| 5782 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
| 5783 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
| 5784 | |||
| 5785 | hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION; | ||
| 5786 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; | ||
| 5787 | hdr.PageNumber = 1; | ||
| 5788 | cfg.cfghdr.hdr = &hdr; | ||
| 5789 | cfg.physAddr = -1; | ||
| 5790 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 5791 | |||
| 5792 | if (mpt_config(ioc, &cfg) != 0) { | ||
| 5793 | rc = 0; | ||
| 5794 | goto out; | ||
| 5795 | } | ||
| 5796 | |||
| 5797 | if (!hdr.PageLength) { | ||
| 5798 | rc = 0; | ||
| 5799 | goto out; | ||
| 5800 | } | ||
| 5801 | |||
| 5802 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
| 5803 | &dma_handle); | ||
| 5804 | |||
| 5805 | if (!buffer) { | ||
| 5806 | rc = 0; | ||
| 5807 | goto out; | ||
| 5808 | } | ||
| 5809 | |||
| 5810 | cfg.physAddr = dma_handle; | ||
| 5811 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 5812 | cfg.pageAddr = phys_disk_num; | ||
| 5813 | |||
| 5814 | if (mpt_config(ioc, &cfg) != 0) { | ||
| 5815 | rc = 0; | ||
| 5816 | goto out; | ||
| 5817 | } | ||
| 5818 | |||
| 5819 | rc = buffer->NumPhysDiskPaths; | ||
| 5820 | out: | ||
| 5821 | |||
| 5822 | if (buffer) | ||
| 5823 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
| 5824 | dma_handle); | ||
| 5825 | |||
| 5826 | return rc; | ||
| 5827 | } | ||
| 5828 | EXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths); | ||
| 5829 | |||
| 5830 | /** | ||
| 5831 | * mpt_raid_phys_disk_pg1 - returns phys disk page 1 | ||
| 5832 | * @ioc: Pointer to a Adapter Structure | ||
| 5833 | * @phys_disk_num: io unit unique phys disk num generated by the ioc | ||
| 5834 | * @phys_disk: requested payload data returned | ||
| 5835 | * | ||
| 5836 | * Return: | ||
| 5837 | * 0 on success | ||
| 5838 | * -EFAULT if read of config page header fails or data pointer not NULL | ||
| 5839 | * -ENOMEM if pci_alloc failed | ||
| 5840 | **/ | ||
| 5841 | int | ||
| 5842 | mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num, | ||
| 5843 | RaidPhysDiskPage1_t *phys_disk) | ||
| 5844 | { | ||
| 5845 | CONFIGPARMS cfg; | ||
| 5846 | ConfigPageHeader_t hdr; | ||
| 5847 | dma_addr_t dma_handle; | ||
| 5848 | pRaidPhysDiskPage1_t buffer = NULL; | ||
| 5849 | int rc; | ||
| 5850 | int i; | ||
| 5851 | __le64 sas_address; | ||
| 5852 | |||
| 5853 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
| 5854 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
| 5855 | rc = 0; | ||
| 5856 | |||
| 5857 | hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION; | ||
| 5858 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; | ||
| 5859 | hdr.PageNumber = 1; | ||
| 5860 | cfg.cfghdr.hdr = &hdr; | ||
| 5861 | cfg.physAddr = -1; | ||
| 5862 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 5863 | |||
| 5864 | if (mpt_config(ioc, &cfg) != 0) { | ||
| 5865 | rc = -EFAULT; | ||
| 5866 | goto out; | ||
| 5867 | } | ||
| 5868 | |||
| 5869 | if (!hdr.PageLength) { | ||
| 5870 | rc = -EFAULT; | ||
| 5871 | goto out; | ||
| 5872 | } | ||
| 5873 | |||
| 5874 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
| 5875 | &dma_handle); | ||
| 5876 | |||
| 5877 | if (!buffer) { | ||
| 5878 | rc = -ENOMEM; | ||
| 5879 | goto out; | ||
| 5880 | } | ||
| 5881 | |||
| 5882 | cfg.physAddr = dma_handle; | ||
| 5883 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 5884 | cfg.pageAddr = phys_disk_num; | ||
| 5885 | |||
| 5886 | if (mpt_config(ioc, &cfg) != 0) { | ||
| 5887 | rc = -EFAULT; | ||
| 5888 | goto out; | ||
| 5889 | } | ||
| 5890 | |||
| 5891 | phys_disk->NumPhysDiskPaths = buffer->NumPhysDiskPaths; | ||
| 5892 | phys_disk->PhysDiskNum = phys_disk_num; | ||
| 5893 | for (i = 0; i < phys_disk->NumPhysDiskPaths; i++) { | ||
| 5894 | phys_disk->Path[i].PhysDiskID = buffer->Path[i].PhysDiskID; | ||
| 5895 | phys_disk->Path[i].PhysDiskBus = buffer->Path[i].PhysDiskBus; | ||
| 5896 | phys_disk->Path[i].OwnerIdentifier = | ||
| 5897 | buffer->Path[i].OwnerIdentifier; | ||
| 5898 | phys_disk->Path[i].Flags = le16_to_cpu(buffer->Path[i].Flags); | ||
| 5899 | memcpy(&sas_address, &buffer->Path[i].WWID, sizeof(__le64)); | ||
| 5900 | sas_address = le64_to_cpu(sas_address); | ||
| 5901 | memcpy(&phys_disk->Path[i].WWID, &sas_address, sizeof(__le64)); | ||
| 5902 | memcpy(&sas_address, | ||
| 5903 | &buffer->Path[i].OwnerWWID, sizeof(__le64)); | ||
| 5904 | sas_address = le64_to_cpu(sas_address); | ||
| 5905 | memcpy(&phys_disk->Path[i].OwnerWWID, | ||
| 5906 | &sas_address, sizeof(__le64)); | ||
| 5907 | } | ||
| 5908 | |||
| 5909 | out: | ||
| 5910 | |||
| 5911 | if (buffer) | ||
| 5912 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
| 5913 | dma_handle); | ||
| 5914 | |||
| 5915 | return rc; | ||
| 5916 | } | ||
| 5917 | EXPORT_SYMBOL(mpt_raid_phys_disk_pg1); | ||
| 5918 | |||
| 5919 | |||
| 5920 | /** | ||
| 5454 | * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes | 5921 | * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes |
| 5455 | * @ioc: Pointer to a Adapter Strucutre | 5922 | * @ioc: Pointer to a Adapter Strucutre |
| 5456 | * | 5923 | * |
| @@ -5775,30 +6242,28 @@ mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc) | |||
| 5775 | * SendEventNotification - Send EventNotification (on or off) request to adapter | 6242 | * SendEventNotification - Send EventNotification (on or off) request to adapter |
| 5776 | * @ioc: Pointer to MPT_ADAPTER structure | 6243 | * @ioc: Pointer to MPT_ADAPTER structure |
| 5777 | * @EvSwitch: Event switch flags | 6244 | * @EvSwitch: Event switch flags |
| 6245 | * @sleepFlag: Specifies whether the process can sleep | ||
| 5778 | */ | 6246 | */ |
| 5779 | static int | 6247 | static int |
| 5780 | SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch) | 6248 | SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, int sleepFlag) |
| 5781 | { | 6249 | { |
| 5782 | EventNotification_t *evnp; | 6250 | EventNotification_t evn; |
| 6251 | MPIDefaultReply_t reply_buf; | ||
| 5783 | 6252 | ||
| 5784 | evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc); | 6253 | memset(&evn, 0, sizeof(EventNotification_t)); |
| 5785 | if (evnp == NULL) { | 6254 | memset(&reply_buf, 0, sizeof(MPIDefaultReply_t)); |
| 5786 | devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", | ||
| 5787 | ioc->name)); | ||
| 5788 | return 0; | ||
| 5789 | } | ||
| 5790 | memset(evnp, 0, sizeof(*evnp)); | ||
| 5791 | |||
| 5792 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); | ||
| 5793 | 6255 | ||
| 5794 | evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; | 6256 | evn.Function = MPI_FUNCTION_EVENT_NOTIFICATION; |
| 5795 | evnp->ChainOffset = 0; | 6257 | evn.Switch = EvSwitch; |
| 5796 | evnp->MsgFlags = 0; | 6258 | evn.MsgContext = cpu_to_le32(mpt_base_index << 16); |
| 5797 | evnp->Switch = EvSwitch; | ||
| 5798 | 6259 | ||
| 5799 | mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp); | 6260 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 6261 | "Sending EventNotification (%d) request %p\n", | ||
| 6262 | ioc->name, EvSwitch, &evn)); | ||
| 5800 | 6263 | ||
| 5801 | return 0; | 6264 | return mpt_handshake_req_reply_wait(ioc, sizeof(EventNotification_t), |
| 6265 | (u32 *)&evn, sizeof(MPIDefaultReply_t), (u16 *)&reply_buf, 30, | ||
| 6266 | sleepFlag); | ||
| 5802 | } | 6267 | } |
| 5803 | 6268 | ||
| 5804 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6269 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| @@ -5814,7 +6279,7 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) | |||
| 5814 | 6279 | ||
| 5815 | if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { | 6280 | if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { |
| 5816 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n", | 6281 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n", |
| 5817 | ioc->name,__func__)); | 6282 | ioc->name, __func__)); |
| 5818 | return -1; | 6283 | return -1; |
| 5819 | } | 6284 | } |
| 5820 | 6285 | ||
| @@ -5851,12 +6316,19 @@ int | |||
| 5851 | mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | 6316 | mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) |
| 5852 | { | 6317 | { |
| 5853 | Config_t *pReq; | 6318 | Config_t *pReq; |
| 6319 | ConfigReply_t *pReply; | ||
| 5854 | ConfigExtendedPageHeader_t *pExtHdr = NULL; | 6320 | ConfigExtendedPageHeader_t *pExtHdr = NULL; |
| 5855 | MPT_FRAME_HDR *mf; | 6321 | MPT_FRAME_HDR *mf; |
| 5856 | unsigned long flags; | 6322 | int ii; |
| 5857 | int ii, rc; | ||
| 5858 | int flagsLength; | 6323 | int flagsLength; |
| 5859 | int in_isr; | 6324 | long timeout; |
| 6325 | int ret; | ||
| 6326 | u8 page_type = 0, extend_page; | ||
| 6327 | unsigned long timeleft; | ||
| 6328 | unsigned long flags; | ||
| 6329 | int in_isr; | ||
| 6330 | u8 issue_hard_reset = 0; | ||
| 6331 | u8 retry_count = 0; | ||
| 5860 | 6332 | ||
| 5861 | /* Prevent calling wait_event() (below), if caller happens | 6333 | /* Prevent calling wait_event() (below), if caller happens |
| 5862 | * to be in ISR context, because that is fatal! | 6334 | * to be in ISR context, because that is fatal! |
| @@ -5866,15 +6338,43 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | |||
| 5866 | dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n", | 6338 | dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n", |
| 5867 | ioc->name)); | 6339 | ioc->name)); |
| 5868 | return -EPERM; | 6340 | return -EPERM; |
| 6341 | } | ||
| 6342 | |||
| 6343 | /* don't send a config page during diag reset */ | ||
| 6344 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
| 6345 | if (ioc->ioc_reset_in_progress) { | ||
| 6346 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 6347 | "%s: busy with host reset\n", ioc->name, __func__)); | ||
| 6348 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 6349 | return -EBUSY; | ||
| 6350 | } | ||
| 6351 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 6352 | |||
| 6353 | /* don't send if no chance of success */ | ||
| 6354 | if (!ioc->active || | ||
| 6355 | mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_OPERATIONAL) { | ||
| 6356 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 6357 | "%s: ioc not operational, %d, %xh\n", | ||
| 6358 | ioc->name, __func__, ioc->active, | ||
| 6359 | mpt_GetIocState(ioc, 0))); | ||
| 6360 | return -EFAULT; | ||
| 5869 | } | 6361 | } |
| 5870 | 6362 | ||
| 6363 | retry_config: | ||
| 6364 | mutex_lock(&ioc->mptbase_cmds.mutex); | ||
| 6365 | /* init the internal cmd struct */ | ||
| 6366 | memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE); | ||
| 6367 | INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status) | ||
| 6368 | |||
| 5871 | /* Get and Populate a free Frame | 6369 | /* Get and Populate a free Frame |
| 5872 | */ | 6370 | */ |
| 5873 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { | 6371 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { |
| 5874 | dcprintk(ioc, printk(MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n", | 6372 | dcprintk(ioc, printk(MYIOC_s_WARN_FMT |
| 5875 | ioc->name)); | 6373 | "mpt_config: no msg frames!\n", ioc->name)); |
| 5876 | return -EAGAIN; | 6374 | ret = -EAGAIN; |
| 6375 | goto out; | ||
| 5877 | } | 6376 | } |
| 6377 | |||
| 5878 | pReq = (Config_t *)mf; | 6378 | pReq = (Config_t *)mf; |
| 5879 | pReq->Action = pCfg->action; | 6379 | pReq->Action = pCfg->action; |
| 5880 | pReq->Reserved = 0; | 6380 | pReq->Reserved = 0; |
| @@ -5900,7 +6400,9 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | |||
| 5900 | pReq->ExtPageType = pExtHdr->ExtPageType; | 6400 | pReq->ExtPageType = pExtHdr->ExtPageType; |
| 5901 | pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; | 6401 | pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; |
| 5902 | 6402 | ||
| 5903 | /* Page Length must be treated as a reserved field for the extended header. */ | 6403 | /* Page Length must be treated as a reserved field for the |
| 6404 | * extended header. | ||
| 6405 | */ | ||
| 5904 | pReq->Header.PageLength = 0; | 6406 | pReq->Header.PageLength = 0; |
| 5905 | } | 6407 | } |
| 5906 | 6408 | ||
| @@ -5913,78 +6415,91 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | |||
| 5913 | else | 6415 | else |
| 5914 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; | 6416 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; |
| 5915 | 6417 | ||
| 5916 | if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) { | 6418 | if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == |
| 6419 | MPI_CONFIG_PAGETYPE_EXTENDED) { | ||
| 5917 | flagsLength |= pExtHdr->ExtPageLength * 4; | 6420 | flagsLength |= pExtHdr->ExtPageLength * 4; |
| 5918 | 6421 | page_type = pReq->ExtPageType; | |
| 5919 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n", | 6422 | extend_page = 1; |
| 5920 | ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action)); | 6423 | } else { |
| 5921 | } | ||
| 5922 | else { | ||
| 5923 | flagsLength |= pCfg->cfghdr.hdr->PageLength * 4; | 6424 | flagsLength |= pCfg->cfghdr.hdr->PageLength * 4; |
| 5924 | 6425 | page_type = pReq->Header.PageType; | |
| 5925 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n", | 6426 | extend_page = 0; |
| 5926 | ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action)); | ||
| 5927 | } | 6427 | } |
| 5928 | 6428 | ||
| 5929 | mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr); | 6429 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 5930 | 6430 | "Sending Config request type 0x%x, page 0x%x and action %d\n", | |
| 5931 | /* Append pCfg pointer to end of mf | 6431 | ioc->name, page_type, pReq->Header.PageNumber, pReq->Action)); |
| 5932 | */ | ||
| 5933 | *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg; | ||
| 5934 | |||
| 5935 | /* Initalize the timer | ||
| 5936 | */ | ||
| 5937 | init_timer_on_stack(&pCfg->timer); | ||
| 5938 | pCfg->timer.data = (unsigned long) ioc; | ||
| 5939 | pCfg->timer.function = mpt_timer_expired; | ||
| 5940 | pCfg->wait_done = 0; | ||
| 5941 | |||
| 5942 | /* Set the timer; ensure 10 second minimum */ | ||
| 5943 | if (pCfg->timeout < 10) | ||
| 5944 | pCfg->timer.expires = jiffies + HZ*10; | ||
| 5945 | else | ||
| 5946 | pCfg->timer.expires = jiffies + HZ*pCfg->timeout; | ||
| 5947 | |||
| 5948 | /* Add to end of Q, set timer and then issue this command */ | ||
| 5949 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
| 5950 | list_add_tail(&pCfg->linkage, &ioc->configQ); | ||
| 5951 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
| 5952 | 6432 | ||
| 5953 | add_timer(&pCfg->timer); | 6433 | ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr); |
| 6434 | timeout = (pCfg->timeout < 15) ? HZ*15 : HZ*pCfg->timeout; | ||
| 5954 | mpt_put_msg_frame(mpt_base_index, ioc, mf); | 6435 | mpt_put_msg_frame(mpt_base_index, ioc, mf); |
| 5955 | wait_event(mpt_waitq, pCfg->wait_done); | 6436 | timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, |
| 6437 | timeout); | ||
| 6438 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | ||
| 6439 | ret = -ETIME; | ||
| 6440 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 6441 | "Failed Sending Config request type 0x%x, page 0x%x," | ||
| 6442 | " action %d, status %xh, time left %ld\n\n", | ||
| 6443 | ioc->name, page_type, pReq->Header.PageNumber, | ||
| 6444 | pReq->Action, ioc->mptbase_cmds.status, timeleft)); | ||
| 6445 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) | ||
| 6446 | goto out; | ||
| 6447 | if (!timeleft) | ||
| 6448 | issue_hard_reset = 1; | ||
| 6449 | goto out; | ||
| 6450 | } | ||
| 5956 | 6451 | ||
| 5957 | /* mf has been freed - do not access */ | 6452 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { |
| 6453 | ret = -1; | ||
| 6454 | goto out; | ||
| 6455 | } | ||
| 6456 | pReply = (ConfigReply_t *)ioc->mptbase_cmds.reply; | ||
| 6457 | ret = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
| 6458 | if (ret == MPI_IOCSTATUS_SUCCESS) { | ||
| 6459 | if (extend_page) { | ||
| 6460 | pCfg->cfghdr.ehdr->ExtPageLength = | ||
| 6461 | le16_to_cpu(pReply->ExtPageLength); | ||
| 6462 | pCfg->cfghdr.ehdr->ExtPageType = | ||
| 6463 | pReply->ExtPageType; | ||
| 6464 | } | ||
| 6465 | pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion; | ||
| 6466 | pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength; | ||
| 6467 | pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber; | ||
| 6468 | pCfg->cfghdr.hdr->PageType = pReply->Header.PageType; | ||
| 5958 | 6469 | ||
| 5959 | rc = pCfg->status; | 6470 | } |
| 5960 | 6471 | ||
| 5961 | return rc; | 6472 | if (retry_count) |
| 5962 | } | 6473 | printk(MYIOC_s_INFO_FMT "Retry completed " |
| 6474 | "ret=0x%x timeleft=%ld\n", | ||
| 6475 | ioc->name, ret, timeleft); | ||
| 5963 | 6476 | ||
| 5964 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6477 | dcprintk(ioc, printk(KERN_DEBUG "IOCStatus=%04xh, IOCLogInfo=%08xh\n", |
| 5965 | /** | 6478 | ret, le32_to_cpu(pReply->IOCLogInfo))); |
| 5966 | * mpt_timer_expired - Callback for timer process. | ||
| 5967 | * Used only internal config functionality. | ||
| 5968 | * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long | ||
| 5969 | */ | ||
| 5970 | static void | ||
| 5971 | mpt_timer_expired(unsigned long data) | ||
| 5972 | { | ||
| 5973 | MPT_ADAPTER *ioc = (MPT_ADAPTER *) data; | ||
| 5974 | |||
| 5975 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired! \n", ioc->name)); | ||
| 5976 | 6479 | ||
| 5977 | /* Perform a FW reload */ | 6480 | out: |
| 5978 | if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) | ||
| 5979 | printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name); | ||
| 5980 | 6481 | ||
| 5981 | /* No more processing. | 6482 | CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status) |
| 5982 | * Hard reset clean-up will wake up | 6483 | mutex_unlock(&ioc->mptbase_cmds.mutex); |
| 5983 | * process and free all resources. | 6484 | if (issue_hard_reset) { |
| 5984 | */ | 6485 | issue_hard_reset = 0; |
| 5985 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired complete!\n", ioc->name)); | 6486 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", |
| 6487 | ioc->name, __func__); | ||
| 6488 | mpt_HardResetHandler(ioc, CAN_SLEEP); | ||
| 6489 | mpt_free_msg_frame(ioc, mf); | ||
| 6490 | /* attempt one retry for a timed out command */ | ||
| 6491 | if (!retry_count) { | ||
| 6492 | printk(MYIOC_s_INFO_FMT | ||
| 6493 | "Attempting Retry Config request" | ||
| 6494 | " type 0x%x, page 0x%x," | ||
| 6495 | " action %d\n", ioc->name, page_type, | ||
| 6496 | pCfg->cfghdr.hdr->PageNumber, pCfg->action); | ||
| 6497 | retry_count++; | ||
| 6498 | goto retry_config; | ||
| 6499 | } | ||
| 6500 | } | ||
| 6501 | return ret; | ||
| 5986 | 6502 | ||
| 5987 | return; | ||
| 5988 | } | 6503 | } |
| 5989 | 6504 | ||
| 5990 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6505 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| @@ -5998,41 +6513,34 @@ mpt_timer_expired(unsigned long data) | |||
| 5998 | static int | 6513 | static int |
| 5999 | mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | 6514 | mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) |
| 6000 | { | 6515 | { |
| 6001 | CONFIGPARMS *pCfg; | 6516 | switch (reset_phase) { |
| 6002 | unsigned long flags; | 6517 | case MPT_IOC_SETUP_RESET: |
| 6003 | 6518 | ioc->taskmgmt_quiesce_io = 1; | |
| 6004 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 6519 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 6005 | ": IOC %s_reset routed to MPT base driver!\n", | 6520 | "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__)); |
| 6006 | ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( | 6521 | break; |
| 6007 | reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); | 6522 | case MPT_IOC_PRE_RESET: |
| 6008 | 6523 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | |
| 6009 | if (reset_phase == MPT_IOC_SETUP_RESET) { | 6524 | "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__)); |
| 6010 | ; | 6525 | break; |
| 6011 | } else if (reset_phase == MPT_IOC_PRE_RESET) { | 6526 | case MPT_IOC_POST_RESET: |
| 6012 | /* If the internal config Q is not empty - | 6527 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 6013 | * delete timer. MF resources will be freed when | 6528 | "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__)); |
| 6014 | * the FIFO's are primed. | 6529 | /* wake up mptbase_cmds */ |
| 6015 | */ | 6530 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) { |
| 6016 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 6531 | ioc->mptbase_cmds.status |= |
| 6017 | list_for_each_entry(pCfg, &ioc->configQ, linkage) | 6532 | MPT_MGMT_STATUS_DID_IOCRESET; |
| 6018 | del_timer(&pCfg->timer); | 6533 | complete(&ioc->mptbase_cmds.done); |
| 6019 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
| 6020 | |||
| 6021 | } else { | ||
| 6022 | CONFIGPARMS *pNext; | ||
| 6023 | |||
| 6024 | /* Search the configQ for internal commands. | ||
| 6025 | * Flush the Q, and wake up all suspended threads. | ||
| 6026 | */ | ||
| 6027 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
| 6028 | list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) { | ||
| 6029 | list_del(&pCfg->linkage); | ||
| 6030 | |||
| 6031 | pCfg->status = MPT_CONFIG_ERROR; | ||
| 6032 | pCfg->wait_done = 1; | ||
| 6033 | wake_up(&mpt_waitq); | ||
| 6034 | } | 6534 | } |
| 6035 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 6535 | /* wake up taskmgmt_cmds */ |
| 6536 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) { | ||
| 6537 | ioc->taskmgmt_cmds.status |= | ||
| 6538 | MPT_MGMT_STATUS_DID_IOCRESET; | ||
| 6539 | complete(&ioc->taskmgmt_cmds.done); | ||
| 6540 | } | ||
| 6541 | break; | ||
| 6542 | default: | ||
| 6543 | break; | ||
| 6036 | } | 6544 | } |
| 6037 | 6545 | ||
| 6038 | return 1; /* currently means nothing really */ | 6546 | return 1; /* currently means nothing really */ |
| @@ -6344,6 +6852,59 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh | |||
| 6344 | 6852 | ||
| 6345 | *size = y; | 6853 | *size = y; |
| 6346 | } | 6854 | } |
| 6855 | /** | ||
| 6856 | * mpt_set_taskmgmt_in_progress_flag - set flags associated with task managment | ||
| 6857 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 6858 | * | ||
| 6859 | * Returns 0 for SUCCESS or -1 if FAILED. | ||
| 6860 | * | ||
| 6861 | * If -1 is return, then it was not possible to set the flags | ||
| 6862 | **/ | ||
| 6863 | int | ||
| 6864 | mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc) | ||
| 6865 | { | ||
| 6866 | unsigned long flags; | ||
| 6867 | int retval; | ||
| 6868 | |||
| 6869 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
| 6870 | if (ioc->ioc_reset_in_progress || ioc->taskmgmt_in_progress || | ||
| 6871 | (ioc->alt_ioc && ioc->alt_ioc->taskmgmt_in_progress)) { | ||
| 6872 | retval = -1; | ||
| 6873 | goto out; | ||
| 6874 | } | ||
| 6875 | retval = 0; | ||
| 6876 | ioc->taskmgmt_in_progress = 1; | ||
| 6877 | ioc->taskmgmt_quiesce_io = 1; | ||
| 6878 | if (ioc->alt_ioc) { | ||
| 6879 | ioc->alt_ioc->taskmgmt_in_progress = 1; | ||
| 6880 | ioc->alt_ioc->taskmgmt_quiesce_io = 1; | ||
| 6881 | } | ||
| 6882 | out: | ||
| 6883 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 6884 | return retval; | ||
| 6885 | } | ||
| 6886 | EXPORT_SYMBOL(mpt_set_taskmgmt_in_progress_flag); | ||
| 6887 | |||
| 6888 | /** | ||
| 6889 | * mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task managment | ||
| 6890 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 6891 | * | ||
| 6892 | **/ | ||
| 6893 | void | ||
| 6894 | mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc) | ||
| 6895 | { | ||
| 6896 | unsigned long flags; | ||
| 6897 | |||
| 6898 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
| 6899 | ioc->taskmgmt_in_progress = 0; | ||
| 6900 | ioc->taskmgmt_quiesce_io = 0; | ||
| 6901 | if (ioc->alt_ioc) { | ||
| 6902 | ioc->alt_ioc->taskmgmt_in_progress = 0; | ||
| 6903 | ioc->alt_ioc->taskmgmt_quiesce_io = 0; | ||
| 6904 | } | ||
| 6905 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 6906 | } | ||
| 6907 | EXPORT_SYMBOL(mpt_clear_taskmgmt_in_progress_flag); | ||
| 6347 | 6908 | ||
| 6348 | 6909 | ||
| 6349 | /** | 6910 | /** |
| @@ -6397,7 +6958,9 @@ int | |||
| 6397 | mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) | 6958 | mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) |
| 6398 | { | 6959 | { |
| 6399 | int rc; | 6960 | int rc; |
| 6961 | u8 cb_idx; | ||
| 6400 | unsigned long flags; | 6962 | unsigned long flags; |
| 6963 | unsigned long time_count; | ||
| 6401 | 6964 | ||
| 6402 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name)); | 6965 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name)); |
| 6403 | #ifdef MFCNT | 6966 | #ifdef MFCNT |
| @@ -6410,14 +6973,15 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) | |||
| 6410 | /* Reset the adapter. Prevent more than 1 call to | 6973 | /* Reset the adapter. Prevent more than 1 call to |
| 6411 | * mpt_do_ioc_recovery at any instant in time. | 6974 | * mpt_do_ioc_recovery at any instant in time. |
| 6412 | */ | 6975 | */ |
| 6413 | spin_lock_irqsave(&ioc->diagLock, flags); | 6976 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
| 6414 | if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){ | 6977 | if (ioc->ioc_reset_in_progress) { |
| 6415 | spin_unlock_irqrestore(&ioc->diagLock, flags); | 6978 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); |
| 6416 | return 0; | 6979 | return 0; |
| 6417 | } else { | ||
| 6418 | ioc->diagPending = 1; | ||
| 6419 | } | 6980 | } |
| 6420 | spin_unlock_irqrestore(&ioc->diagLock, flags); | 6981 | ioc->ioc_reset_in_progress = 1; |
| 6982 | if (ioc->alt_ioc) | ||
| 6983 | ioc->alt_ioc->ioc_reset_in_progress = 1; | ||
| 6984 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 6421 | 6985 | ||
| 6422 | /* FIXME: If do_ioc_recovery fails, repeat.... | 6986 | /* FIXME: If do_ioc_recovery fails, repeat.... |
| 6423 | */ | 6987 | */ |
| @@ -6427,47 +6991,57 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) | |||
| 6427 | * Prevents timeouts occurring during a diagnostic reset...very bad. | 6991 | * Prevents timeouts occurring during a diagnostic reset...very bad. |
| 6428 | * For all other protocol drivers, this is a no-op. | 6992 | * For all other protocol drivers, this is a no-op. |
| 6429 | */ | 6993 | */ |
| 6430 | { | 6994 | for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { |
| 6431 | u8 cb_idx; | 6995 | if (MptResetHandlers[cb_idx]) { |
| 6432 | int r = 0; | 6996 | mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET); |
| 6433 | 6997 | if (ioc->alt_ioc) | |
| 6434 | for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { | 6998 | mpt_signal_reset(cb_idx, ioc->alt_ioc, |
| 6435 | if (MptResetHandlers[cb_idx]) { | 6999 | MPT_IOC_SETUP_RESET); |
| 6436 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n", | ||
| 6437 | ioc->name, cb_idx)); | ||
| 6438 | r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET); | ||
| 6439 | if (ioc->alt_ioc) { | ||
| 6440 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n", | ||
| 6441 | ioc->name, ioc->alt_ioc->name, cb_idx)); | ||
| 6442 | r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET); | ||
| 6443 | } | ||
| 6444 | } | ||
| 6445 | } | 7000 | } |
| 6446 | } | 7001 | } |
| 6447 | 7002 | ||
| 6448 | if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) { | 7003 | time_count = jiffies; |
| 6449 | printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc); | 7004 | rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag); |
| 7005 | if (rc != 0) { | ||
| 7006 | printk(KERN_WARNING MYNAM | ||
| 7007 | ": WARNING - (%d) Cannot recover %s\n", rc, ioc->name); | ||
| 7008 | } else { | ||
| 7009 | if (ioc->hard_resets < -1) | ||
| 7010 | ioc->hard_resets++; | ||
| 6450 | } | 7011 | } |
| 6451 | ioc->reload_fw = 0; | ||
| 6452 | if (ioc->alt_ioc) | ||
| 6453 | ioc->alt_ioc->reload_fw = 0; | ||
| 6454 | 7012 | ||
| 6455 | spin_lock_irqsave(&ioc->diagLock, flags); | 7013 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
| 6456 | ioc->diagPending = 0; | 7014 | ioc->ioc_reset_in_progress = 0; |
| 6457 | if (ioc->alt_ioc) | 7015 | ioc->taskmgmt_quiesce_io = 0; |
| 6458 | ioc->alt_ioc->diagPending = 0; | 7016 | ioc->taskmgmt_in_progress = 0; |
| 6459 | spin_unlock_irqrestore(&ioc->diagLock, flags); | 7017 | if (ioc->alt_ioc) { |
| 7018 | ioc->alt_ioc->ioc_reset_in_progress = 0; | ||
| 7019 | ioc->alt_ioc->taskmgmt_quiesce_io = 0; | ||
| 7020 | ioc->alt_ioc->taskmgmt_in_progress = 0; | ||
| 7021 | } | ||
| 7022 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 6460 | 7023 | ||
| 6461 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler rc = %d!\n", ioc->name, rc)); | 7024 | dtmprintk(ioc, |
| 7025 | printk(MYIOC_s_DEBUG_FMT | ||
| 7026 | "HardResetHandler: completed (%d seconds): %s\n", ioc->name, | ||
| 7027 | jiffies_to_msecs(jiffies - time_count)/1000, ((rc == 0) ? | ||
| 7028 | "SUCCESS" : "FAILED"))); | ||
| 6462 | 7029 | ||
| 6463 | return rc; | 7030 | return rc; |
| 6464 | } | 7031 | } |
| 6465 | 7032 | ||
| 6466 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 7033 | #ifdef CONFIG_FUSION_LOGGING |
| 6467 | static void | 7034 | static void |
| 6468 | EventDescriptionStr(u8 event, u32 evData0, char *evStr) | 7035 | mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply) |
| 6469 | { | 7036 | { |
| 6470 | char *ds = NULL; | 7037 | char *ds = NULL; |
| 7038 | u32 evData0; | ||
| 7039 | int ii; | ||
| 7040 | u8 event; | ||
| 7041 | char *evStr = ioc->evStr; | ||
| 7042 | |||
| 7043 | event = le32_to_cpu(pEventReply->Event) & 0xFF; | ||
| 7044 | evData0 = le32_to_cpu(pEventReply->Data[0]); | ||
| 6471 | 7045 | ||
| 6472 | switch(event) { | 7046 | switch(event) { |
| 6473 | case MPI_EVENT_NONE: | 7047 | case MPI_EVENT_NONE: |
| @@ -6501,9 +7075,9 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
| 6501 | if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP) | 7075 | if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP) |
| 6502 | ds = "Loop State(LIP) Change"; | 7076 | ds = "Loop State(LIP) Change"; |
| 6503 | else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE) | 7077 | else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE) |
| 6504 | ds = "Loop State(LPE) Change"; /* ??? */ | 7078 | ds = "Loop State(LPE) Change"; |
| 6505 | else | 7079 | else |
| 6506 | ds = "Loop State(LPB) Change"; /* ??? */ | 7080 | ds = "Loop State(LPB) Change"; |
| 6507 | break; | 7081 | break; |
| 6508 | case MPI_EVENT_LOGOUT: | 7082 | case MPI_EVENT_LOGOUT: |
| 6509 | ds = "Logout"; | 7083 | ds = "Logout"; |
| @@ -6703,28 +7277,65 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
| 6703 | } | 7277 | } |
| 6704 | case MPI_EVENT_IR2: | 7278 | case MPI_EVENT_IR2: |
| 6705 | { | 7279 | { |
| 7280 | u8 id = (u8)(evData0); | ||
| 7281 | u8 channel = (u8)(evData0 >> 8); | ||
| 7282 | u8 phys_num = (u8)(evData0 >> 24); | ||
| 6706 | u8 ReasonCode = (u8)(evData0 >> 16); | 7283 | u8 ReasonCode = (u8)(evData0 >> 16); |
| 7284 | |||
| 6707 | switch (ReasonCode) { | 7285 | switch (ReasonCode) { |
| 6708 | case MPI_EVENT_IR2_RC_LD_STATE_CHANGED: | 7286 | case MPI_EVENT_IR2_RC_LD_STATE_CHANGED: |
| 6709 | ds = "IR2: LD State Changed"; | 7287 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
| 7288 | "IR2: LD State Changed: " | ||
| 7289 | "id=%d channel=%d phys_num=%d", | ||
| 7290 | id, channel, phys_num); | ||
| 6710 | break; | 7291 | break; |
| 6711 | case MPI_EVENT_IR2_RC_PD_STATE_CHANGED: | 7292 | case MPI_EVENT_IR2_RC_PD_STATE_CHANGED: |
| 6712 | ds = "IR2: PD State Changed"; | 7293 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
| 7294 | "IR2: PD State Changed " | ||
| 7295 | "id=%d channel=%d phys_num=%d", | ||
| 7296 | id, channel, phys_num); | ||
| 6713 | break; | 7297 | break; |
| 6714 | case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL: | 7298 | case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL: |
| 6715 | ds = "IR2: Bad Block Table Full"; | 7299 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
| 7300 | "IR2: Bad Block Table Full: " | ||
| 7301 | "id=%d channel=%d phys_num=%d", | ||
| 7302 | id, channel, phys_num); | ||
| 6716 | break; | 7303 | break; |
| 6717 | case MPI_EVENT_IR2_RC_PD_INSERTED: | 7304 | case MPI_EVENT_IR2_RC_PD_INSERTED: |
| 6718 | ds = "IR2: PD Inserted"; | 7305 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
| 7306 | "IR2: PD Inserted: " | ||
| 7307 | "id=%d channel=%d phys_num=%d", | ||
| 7308 | id, channel, phys_num); | ||
| 6719 | break; | 7309 | break; |
| 6720 | case MPI_EVENT_IR2_RC_PD_REMOVED: | 7310 | case MPI_EVENT_IR2_RC_PD_REMOVED: |
| 6721 | ds = "IR2: PD Removed"; | 7311 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
| 7312 | "IR2: PD Removed: " | ||
| 7313 | "id=%d channel=%d phys_num=%d", | ||
| 7314 | id, channel, phys_num); | ||
| 6722 | break; | 7315 | break; |
| 6723 | case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: | 7316 | case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: |
| 6724 | ds = "IR2: Foreign CFG Detected"; | 7317 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
| 7318 | "IR2: Foreign CFG Detected: " | ||
| 7319 | "id=%d channel=%d phys_num=%d", | ||
| 7320 | id, channel, phys_num); | ||
| 6725 | break; | 7321 | break; |
| 6726 | case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR: | 7322 | case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR: |
| 6727 | ds = "IR2: Rebuild Medium Error"; | 7323 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
| 7324 | "IR2: Rebuild Medium Error: " | ||
| 7325 | "id=%d channel=%d phys_num=%d", | ||
| 7326 | id, channel, phys_num); | ||
| 7327 | break; | ||
| 7328 | case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED: | ||
| 7329 | snprintf(evStr, EVENT_DESCR_STR_SZ, | ||
| 7330 | "IR2: Dual Port Added: " | ||
| 7331 | "id=%d channel=%d phys_num=%d", | ||
| 7332 | id, channel, phys_num); | ||
| 7333 | break; | ||
| 7334 | case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED: | ||
| 7335 | snprintf(evStr, EVENT_DESCR_STR_SZ, | ||
| 7336 | "IR2: Dual Port Removed: " | ||
| 7337 | "id=%d channel=%d phys_num=%d", | ||
| 7338 | id, channel, phys_num); | ||
| 6728 | break; | 7339 | break; |
| 6729 | default: | 7340 | default: |
| 6730 | ds = "IR2"; | 7341 | ds = "IR2"; |
| @@ -6760,13 +7371,18 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
| 6760 | case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: | 7371 | case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: |
| 6761 | { | 7372 | { |
| 6762 | u8 reason = (u8)(evData0); | 7373 | u8 reason = (u8)(evData0); |
| 6763 | u8 port_num = (u8)(evData0 >> 8); | ||
| 6764 | u16 handle = le16_to_cpu(evData0 >> 16); | ||
| 6765 | 7374 | ||
| 6766 | snprintf(evStr, EVENT_DESCR_STR_SZ, | 7375 | switch (reason) { |
| 6767 | "SAS Initiator Device Status Change: reason=0x%02x " | 7376 | case MPI_EVENT_SAS_INIT_RC_ADDED: |
| 6768 | "port=%d handle=0x%04x", | 7377 | ds = "SAS Initiator Status Change: Added"; |
| 6769 | reason, port_num, handle); | 7378 | break; |
| 7379 | case MPI_EVENT_SAS_INIT_RC_REMOVED: | ||
| 7380 | ds = "SAS Initiator Status Change: Deleted"; | ||
| 7381 | break; | ||
| 7382 | default: | ||
| 7383 | ds = "SAS Initiator Status Change"; | ||
| 7384 | break; | ||
| 7385 | } | ||
| 6770 | break; | 7386 | break; |
| 6771 | } | 7387 | } |
| 6772 | 7388 | ||
| @@ -6814,6 +7430,24 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
| 6814 | break; | 7430 | break; |
| 6815 | } | 7431 | } |
| 6816 | 7432 | ||
| 7433 | case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE: | ||
| 7434 | { | ||
| 7435 | u8 reason = (u8)(evData0); | ||
| 7436 | |||
| 7437 | switch (reason) { | ||
| 7438 | case MPI_EVENT_SAS_EXP_RC_ADDED: | ||
| 7439 | ds = "Expander Status Change: Added"; | ||
| 7440 | break; | ||
| 7441 | case MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING: | ||
| 7442 | ds = "Expander Status Change: Deleted"; | ||
| 7443 | break; | ||
| 7444 | default: | ||
| 7445 | ds = "Expander Status Change"; | ||
| 7446 | break; | ||
| 7447 | } | ||
| 7448 | break; | ||
| 7449 | } | ||
| 7450 | |||
| 6817 | /* | 7451 | /* |
| 6818 | * MPT base "custom" events may be added here... | 7452 | * MPT base "custom" events may be added here... |
| 6819 | */ | 7453 | */ |
| @@ -6823,8 +7457,20 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
| 6823 | } | 7457 | } |
| 6824 | if (ds) | 7458 | if (ds) |
| 6825 | strncpy(evStr, ds, EVENT_DESCR_STR_SZ); | 7459 | strncpy(evStr, ds, EVENT_DESCR_STR_SZ); |
| 6826 | } | ||
| 6827 | 7460 | ||
| 7461 | |||
| 7462 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 7463 | "MPT event:(%02Xh) : %s\n", | ||
| 7464 | ioc->name, event, evStr)); | ||
| 7465 | |||
| 7466 | devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM | ||
| 7467 | ": Event data:\n")); | ||
| 7468 | for (ii = 0; ii < le16_to_cpu(pEventReply->EventDataLength); ii++) | ||
| 7469 | devtverboseprintk(ioc, printk(" %08x", | ||
| 7470 | le32_to_cpu(pEventReply->Data[ii]))); | ||
| 7471 | devtverboseprintk(ioc, printk(KERN_DEBUG "\n")); | ||
| 7472 | } | ||
| 7473 | #endif | ||
| 6828 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 7474 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 6829 | /** | 7475 | /** |
| 6830 | * ProcessEventNotification - Route EventNotificationReply to all event handlers | 7476 | * ProcessEventNotification - Route EventNotificationReply to all event handlers |
| @@ -6841,37 +7487,24 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply | |||
| 6841 | { | 7487 | { |
| 6842 | u16 evDataLen; | 7488 | u16 evDataLen; |
| 6843 | u32 evData0 = 0; | 7489 | u32 evData0 = 0; |
| 6844 | // u32 evCtx; | ||
| 6845 | int ii; | 7490 | int ii; |
| 6846 | u8 cb_idx; | 7491 | u8 cb_idx; |
| 6847 | int r = 0; | 7492 | int r = 0; |
| 6848 | int handlers = 0; | 7493 | int handlers = 0; |
| 6849 | char evStr[EVENT_DESCR_STR_SZ]; | ||
| 6850 | u8 event; | 7494 | u8 event; |
| 6851 | 7495 | ||
| 6852 | /* | 7496 | /* |
| 6853 | * Do platform normalization of values | 7497 | * Do platform normalization of values |
| 6854 | */ | 7498 | */ |
| 6855 | event = le32_to_cpu(pEventReply->Event) & 0xFF; | 7499 | event = le32_to_cpu(pEventReply->Event) & 0xFF; |
| 6856 | // evCtx = le32_to_cpu(pEventReply->EventContext); | ||
| 6857 | evDataLen = le16_to_cpu(pEventReply->EventDataLength); | 7500 | evDataLen = le16_to_cpu(pEventReply->EventDataLength); |
| 6858 | if (evDataLen) { | 7501 | if (evDataLen) { |
| 6859 | evData0 = le32_to_cpu(pEventReply->Data[0]); | 7502 | evData0 = le32_to_cpu(pEventReply->Data[0]); |
| 6860 | } | 7503 | } |
| 6861 | 7504 | ||
| 6862 | EventDescriptionStr(event, evData0, evStr); | ||
| 6863 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event:(%02Xh) : %s\n", | ||
| 6864 | ioc->name, | ||
| 6865 | event, | ||
| 6866 | evStr)); | ||
| 6867 | |||
| 6868 | #ifdef CONFIG_FUSION_LOGGING | 7505 | #ifdef CONFIG_FUSION_LOGGING |
| 6869 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 7506 | if (evDataLen) |
| 6870 | ": Event data:\n", ioc->name)); | 7507 | mpt_display_event_info(ioc, pEventReply); |
| 6871 | for (ii = 0; ii < evDataLen; ii++) | ||
| 6872 | devtverboseprintk(ioc, printk(" %08x", | ||
| 6873 | le32_to_cpu(pEventReply->Data[ii]))); | ||
| 6874 | devtverboseprintk(ioc, printk("\n")); | ||
| 6875 | #endif | 7508 | #endif |
| 6876 | 7509 | ||
| 6877 | /* | 7510 | /* |
| @@ -6926,8 +7559,9 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply | |||
| 6926 | */ | 7559 | */ |
| 6927 | for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { | 7560 | for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { |
| 6928 | if (MptEvHandlers[cb_idx]) { | 7561 | if (MptEvHandlers[cb_idx]) { |
| 6929 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n", | 7562 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 6930 | ioc->name, cb_idx)); | 7563 | "Routing Event to event handler #%d\n", |
| 7564 | ioc->name, cb_idx)); | ||
| 6931 | r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply); | 7565 | r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply); |
| 6932 | handlers++; | 7566 | handlers++; |
| 6933 | } | 7567 | } |
| @@ -7011,8 +7645,6 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) | |||
| 7011 | switch (info) { | 7645 | switch (info) { |
| 7012 | case 0x00010000: | 7646 | case 0x00010000: |
| 7013 | desc = "bug! MID not found"; | 7647 | desc = "bug! MID not found"; |
| 7014 | if (ioc->reload_fw == 0) | ||
| 7015 | ioc->reload_fw++; | ||
| 7016 | break; | 7648 | break; |
| 7017 | 7649 | ||
| 7018 | case 0x00020000: | 7650 | case 0x00020000: |
| @@ -7613,7 +8245,6 @@ EXPORT_SYMBOL(mpt_get_msg_frame); | |||
| 7613 | EXPORT_SYMBOL(mpt_put_msg_frame); | 8245 | EXPORT_SYMBOL(mpt_put_msg_frame); |
| 7614 | EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri); | 8246 | EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri); |
| 7615 | EXPORT_SYMBOL(mpt_free_msg_frame); | 8247 | EXPORT_SYMBOL(mpt_free_msg_frame); |
| 7616 | EXPORT_SYMBOL(mpt_add_sge); | ||
| 7617 | EXPORT_SYMBOL(mpt_send_handshake_request); | 8248 | EXPORT_SYMBOL(mpt_send_handshake_request); |
| 7618 | EXPORT_SYMBOL(mpt_verify_adapter); | 8249 | EXPORT_SYMBOL(mpt_verify_adapter); |
| 7619 | EXPORT_SYMBOL(mpt_GetIocState); | 8250 | EXPORT_SYMBOL(mpt_GetIocState); |
| @@ -7650,7 +8281,7 @@ fusion_init(void) | |||
| 7650 | /* Register ourselves (mptbase) in order to facilitate | 8281 | /* Register ourselves (mptbase) in order to facilitate |
| 7651 | * EventNotification handling. | 8282 | * EventNotification handling. |
| 7652 | */ | 8283 | */ |
| 7653 | mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER); | 8284 | mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER); |
| 7654 | 8285 | ||
| 7655 | /* Register for hard reset handling callbacks. | 8286 | /* Register for hard reset handling callbacks. |
| 7656 | */ | 8287 | */ |
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index b3e981d2a506..1c8514dc31ca 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
| @@ -76,8 +76,8 @@ | |||
| 76 | #define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR | 76 | #define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR |
| 77 | #endif | 77 | #endif |
| 78 | 78 | ||
| 79 | #define MPT_LINUX_VERSION_COMMON "3.04.07" | 79 | #define MPT_LINUX_VERSION_COMMON "3.04.10" |
| 80 | #define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.07" | 80 | #define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.09" |
| 81 | #define WHAT_MAGIC_STRING "@" "(" "#" ")" | 81 | #define WHAT_MAGIC_STRING "@" "(" "#" ")" |
| 82 | 82 | ||
| 83 | #define show_mptmod_ver(s,ver) \ | 83 | #define show_mptmod_ver(s,ver) \ |
| @@ -104,6 +104,7 @@ | |||
| 104 | #endif | 104 | #endif |
| 105 | 105 | ||
| 106 | #define MPT_NAME_LENGTH 32 | 106 | #define MPT_NAME_LENGTH 32 |
| 107 | #define MPT_KOBJ_NAME_LEN 20 | ||
| 107 | 108 | ||
| 108 | #define MPT_PROCFS_MPTBASEDIR "mpt" | 109 | #define MPT_PROCFS_MPTBASEDIR "mpt" |
| 109 | /* chg it to "driver/fusion" ? */ | 110 | /* chg it to "driver/fusion" ? */ |
| @@ -134,6 +135,7 @@ | |||
| 134 | 135 | ||
| 135 | #define MPT_COALESCING_TIMEOUT 0x10 | 136 | #define MPT_COALESCING_TIMEOUT 0x10 |
| 136 | 137 | ||
| 138 | |||
| 137 | /* | 139 | /* |
| 138 | * SCSI transfer rate defines. | 140 | * SCSI transfer rate defines. |
| 139 | */ | 141 | */ |
| @@ -161,10 +163,10 @@ | |||
| 161 | /* | 163 | /* |
| 162 | * Set the MAX_SGE value based on user input. | 164 | * Set the MAX_SGE value based on user input. |
| 163 | */ | 165 | */ |
| 164 | #ifdef CONFIG_FUSION_MAX_SGE | 166 | #ifdef CONFIG_FUSION_MAX_SGE |
| 165 | #if CONFIG_FUSION_MAX_SGE < 16 | 167 | #if CONFIG_FUSION_MAX_SGE < 16 |
| 166 | #define MPT_SCSI_SG_DEPTH 16 | 168 | #define MPT_SCSI_SG_DEPTH 16 |
| 167 | #elif CONFIG_FUSION_MAX_SGE > 128 | 169 | #elif CONFIG_FUSION_MAX_SGE > 128 |
| 168 | #define MPT_SCSI_SG_DEPTH 128 | 170 | #define MPT_SCSI_SG_DEPTH 128 |
| 169 | #else | 171 | #else |
| 170 | #define MPT_SCSI_SG_DEPTH CONFIG_FUSION_MAX_SGE | 172 | #define MPT_SCSI_SG_DEPTH CONFIG_FUSION_MAX_SGE |
| @@ -173,6 +175,18 @@ | |||
| 173 | #define MPT_SCSI_SG_DEPTH 40 | 175 | #define MPT_SCSI_SG_DEPTH 40 |
| 174 | #endif | 176 | #endif |
| 175 | 177 | ||
| 178 | #ifdef CONFIG_FUSION_MAX_FC_SGE | ||
| 179 | #if CONFIG_FUSION_MAX_FC_SGE < 16 | ||
| 180 | #define MPT_SCSI_FC_SG_DEPTH 16 | ||
| 181 | #elif CONFIG_FUSION_MAX_FC_SGE > 256 | ||
| 182 | #define MPT_SCSI_FC_SG_DEPTH 256 | ||
| 183 | #else | ||
| 184 | #define MPT_SCSI_FC_SG_DEPTH CONFIG_FUSION_MAX_FC_SGE | ||
| 185 | #endif | ||
| 186 | #else | ||
| 187 | #define MPT_SCSI_FC_SG_DEPTH 40 | ||
| 188 | #endif | ||
| 189 | |||
| 176 | /* debug print string length used for events and iocstatus */ | 190 | /* debug print string length used for events and iocstatus */ |
| 177 | # define EVENT_DESCR_STR_SZ 100 | 191 | # define EVENT_DESCR_STR_SZ 100 |
| 178 | 192 | ||
| @@ -431,38 +445,36 @@ do { \ | |||
| 431 | * IOCTL structure and associated defines | 445 | * IOCTL structure and associated defines |
| 432 | */ | 446 | */ |
| 433 | 447 | ||
| 434 | #define MPT_IOCTL_STATUS_DID_IOCRESET 0x01 /* IOC Reset occurred on the current*/ | ||
| 435 | #define MPT_IOCTL_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */ | ||
| 436 | #define MPT_IOCTL_STATUS_TIMER_ACTIVE 0x04 /* The timer is running */ | ||
| 437 | #define MPT_IOCTL_STATUS_SENSE_VALID 0x08 /* Sense data is valid */ | ||
| 438 | #define MPT_IOCTL_STATUS_COMMAND_GOOD 0x10 /* Command Status GOOD */ | ||
| 439 | #define MPT_IOCTL_STATUS_TMTIMER_ACTIVE 0x20 /* The TM timer is running */ | ||
| 440 | #define MPT_IOCTL_STATUS_TM_FAILED 0x40 /* User TM request failed */ | ||
| 441 | |||
| 442 | #define MPTCTL_RESET_OK 0x01 /* Issue Bus Reset */ | 448 | #define MPTCTL_RESET_OK 0x01 /* Issue Bus Reset */ |
| 443 | 449 | ||
| 444 | typedef struct _MPT_IOCTL { | 450 | #define MPT_MGMT_STATUS_RF_VALID 0x01 /* The Reply Frame is VALID */ |
| 445 | struct _MPT_ADAPTER *ioc; | 451 | #define MPT_MGMT_STATUS_COMMAND_GOOD 0x02 /* Command Status GOOD */ |
| 446 | u8 ReplyFrame[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ | 452 | #define MPT_MGMT_STATUS_PENDING 0x04 /* command is pending */ |
| 447 | u8 sense[MPT_SENSE_BUFFER_ALLOC]; | 453 | #define MPT_MGMT_STATUS_DID_IOCRESET 0x08 /* IOC Reset occurred |
| 448 | int wait_done; /* wake-up value for this ioc */ | 454 | on the current*/ |
| 449 | u8 rsvd; | 455 | #define MPT_MGMT_STATUS_SENSE_VALID 0x10 /* valid sense info */ |
| 450 | u8 status; /* current command status */ | 456 | #define MPT_MGMT_STATUS_TIMER_ACTIVE 0x20 /* obsolete */ |
| 451 | u8 reset; /* 1 if bus reset allowed */ | 457 | #define MPT_MGMT_STATUS_FREE_MF 0x40 /* free the mf from |
| 452 | u8 id; /* target for reset */ | 458 | complete routine */ |
| 453 | struct mutex ioctl_mutex; | 459 | |
| 454 | } MPT_IOCTL; | 460 | #define INITIALIZE_MGMT_STATUS(status) \ |
| 455 | 461 | status = MPT_MGMT_STATUS_PENDING; | |
| 456 | #define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */ | 462 | #define CLEAR_MGMT_STATUS(status) \ |
| 457 | #define MPT_SAS_MGMT_STATUS_COMMAND_GOOD 0x10 /* Command Status GOOD */ | 463 | status = 0; |
| 458 | #define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */ | 464 | #define CLEAR_MGMT_PENDING_STATUS(status) \ |
| 459 | 465 | status &= ~MPT_MGMT_STATUS_PENDING; | |
| 460 | typedef struct _MPT_SAS_MGMT { | 466 | #define SET_MGMT_MSG_CONTEXT(msg_context, value) \ |
| 467 | msg_context = value; | ||
| 468 | |||
| 469 | typedef struct _MPT_MGMT { | ||
| 461 | struct mutex mutex; | 470 | struct mutex mutex; |
| 462 | struct completion done; | 471 | struct completion done; |
| 463 | u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ | 472 | u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ |
| 473 | u8 sense[MPT_SENSE_BUFFER_ALLOC]; | ||
| 464 | u8 status; /* current command status */ | 474 | u8 status; /* current command status */ |
| 465 | }MPT_SAS_MGMT; | 475 | int completion_code; |
| 476 | u32 msg_context; | ||
| 477 | } MPT_MGMT; | ||
| 466 | 478 | ||
| 467 | /* | 479 | /* |
| 468 | * Event Structure and define | 480 | * Event Structure and define |
| @@ -564,6 +576,10 @@ struct mptfc_rport_info | |||
| 564 | u8 flags; | 576 | u8 flags; |
| 565 | }; | 577 | }; |
| 566 | 578 | ||
| 579 | typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr); | ||
| 580 | typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length, | ||
| 581 | dma_addr_t dma_addr); | ||
| 582 | |||
| 567 | /* | 583 | /* |
| 568 | * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS | 584 | * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS |
| 569 | */ | 585 | */ |
| @@ -573,6 +589,10 @@ typedef struct _MPT_ADAPTER | |||
| 573 | int pci_irq; /* This irq */ | 589 | int pci_irq; /* This irq */ |
| 574 | char name[MPT_NAME_LENGTH]; /* "iocN" */ | 590 | char name[MPT_NAME_LENGTH]; /* "iocN" */ |
| 575 | char prod_name[MPT_NAME_LENGTH]; /* "LSIFC9x9" */ | 591 | char prod_name[MPT_NAME_LENGTH]; /* "LSIFC9x9" */ |
| 592 | #ifdef CONFIG_FUSION_LOGGING | ||
| 593 | /* used in mpt_display_event_info */ | ||
| 594 | char evStr[EVENT_DESCR_STR_SZ]; | ||
| 595 | #endif | ||
| 576 | char board_name[16]; | 596 | char board_name[16]; |
| 577 | char board_assembly[16]; | 597 | char board_assembly[16]; |
| 578 | char board_tracer[16]; | 598 | char board_tracer[16]; |
| @@ -600,6 +620,10 @@ typedef struct _MPT_ADAPTER | |||
| 600 | int reply_depth; /* Num Allocated reply frames */ | 620 | int reply_depth; /* Num Allocated reply frames */ |
| 601 | int reply_sz; /* Reply frame size */ | 621 | int reply_sz; /* Reply frame size */ |
| 602 | int num_chain; /* Number of chain buffers */ | 622 | int num_chain; /* Number of chain buffers */ |
| 623 | MPT_ADD_SGE add_sge; /* Pointer to add_sge | ||
| 624 | function */ | ||
| 625 | MPT_ADD_CHAIN add_chain; /* Pointer to add_chain | ||
| 626 | function */ | ||
| 603 | /* Pool of buffers for chaining. ReqToChain | 627 | /* Pool of buffers for chaining. ReqToChain |
| 604 | * and ChainToChain track index of chain buffers. | 628 | * and ChainToChain track index of chain buffers. |
| 605 | * ChainBuffer (DMA) virt/phys addresses. | 629 | * ChainBuffer (DMA) virt/phys addresses. |
| @@ -640,11 +664,8 @@ typedef struct _MPT_ADAPTER | |||
| 640 | RaidCfgData raid_data; /* Raid config. data */ | 664 | RaidCfgData raid_data; /* Raid config. data */ |
| 641 | SasCfgData sas_data; /* Sas config. data */ | 665 | SasCfgData sas_data; /* Sas config. data */ |
| 642 | FcCfgData fc_data; /* Fc config. data */ | 666 | FcCfgData fc_data; /* Fc config. data */ |
| 643 | MPT_IOCTL *ioctl; /* ioctl data pointer */ | ||
| 644 | struct proc_dir_entry *ioc_dentry; | 667 | struct proc_dir_entry *ioc_dentry; |
| 645 | struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ | 668 | struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ |
| 646 | spinlock_t diagLock; /* diagnostic reset lock */ | ||
| 647 | int diagPending; | ||
| 648 | u32 biosVersion; /* BIOS version from IO Unit Page 2 */ | 669 | u32 biosVersion; /* BIOS version from IO Unit Page 2 */ |
| 649 | int eventTypes; /* Event logging parameters */ | 670 | int eventTypes; /* Event logging parameters */ |
| 650 | int eventContext; /* Next event context */ | 671 | int eventContext; /* Next event context */ |
| @@ -652,7 +673,6 @@ typedef struct _MPT_ADAPTER | |||
| 652 | struct _mpt_ioctl_events *events; /* pointer to event log */ | 673 | struct _mpt_ioctl_events *events; /* pointer to event log */ |
| 653 | u8 *cached_fw; /* Pointer to FW */ | 674 | u8 *cached_fw; /* Pointer to FW */ |
| 654 | dma_addr_t cached_fw_dma; | 675 | dma_addr_t cached_fw_dma; |
| 655 | struct list_head configQ; /* linked list of config. requests */ | ||
| 656 | int hs_reply_idx; | 676 | int hs_reply_idx; |
| 657 | #ifndef MFCNT | 677 | #ifndef MFCNT |
| 658 | u32 pad0; | 678 | u32 pad0; |
| @@ -665,9 +685,6 @@ typedef struct _MPT_ADAPTER | |||
| 665 | IOCFactsReply_t facts; | 685 | IOCFactsReply_t facts; |
| 666 | PortFactsReply_t pfacts[2]; | 686 | PortFactsReply_t pfacts[2]; |
| 667 | FCPortPage0_t fc_port_page0[2]; | 687 | FCPortPage0_t fc_port_page0[2]; |
| 668 | struct timer_list persist_timer; /* persist table timer */ | ||
| 669 | int persist_wait_done; /* persist completion flag */ | ||
| 670 | u8 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */ | ||
| 671 | LANPage0_t lan_cnfg_page0; | 688 | LANPage0_t lan_cnfg_page0; |
| 672 | LANPage1_t lan_cnfg_page1; | 689 | LANPage1_t lan_cnfg_page1; |
| 673 | 690 | ||
| @@ -682,23 +699,44 @@ typedef struct _MPT_ADAPTER | |||
| 682 | int aen_event_read_flag; /* flag to indicate event log was read*/ | 699 | int aen_event_read_flag; /* flag to indicate event log was read*/ |
| 683 | u8 FirstWhoInit; | 700 | u8 FirstWhoInit; |
| 684 | u8 upload_fw; /* If set, do a fw upload */ | 701 | u8 upload_fw; /* If set, do a fw upload */ |
| 685 | u8 reload_fw; /* Force a FW Reload on next reset */ | ||
| 686 | u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ | 702 | u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ |
| 687 | u8 pad1[4]; | 703 | u8 pad1[4]; |
| 688 | u8 DoneCtx; | 704 | u8 DoneCtx; |
| 689 | u8 TaskCtx; | 705 | u8 TaskCtx; |
| 690 | u8 InternalCtx; | 706 | u8 InternalCtx; |
| 691 | spinlock_t initializing_hba_lock; | ||
| 692 | int initializing_hba_lock_flag; | ||
| 693 | struct list_head list; | 707 | struct list_head list; |
| 694 | struct net_device *netdev; | 708 | struct net_device *netdev; |
| 695 | struct list_head sas_topology; | 709 | struct list_head sas_topology; |
| 696 | struct mutex sas_topology_mutex; | 710 | struct mutex sas_topology_mutex; |
| 711 | |||
| 712 | struct workqueue_struct *fw_event_q; | ||
| 713 | struct list_head fw_event_list; | ||
| 714 | spinlock_t fw_event_lock; | ||
| 715 | u8 fw_events_off; /* if '1', then ignore events */ | ||
| 716 | char fw_event_q_name[MPT_KOBJ_NAME_LEN]; | ||
| 717 | |||
| 697 | struct mutex sas_discovery_mutex; | 718 | struct mutex sas_discovery_mutex; |
| 698 | u8 sas_discovery_runtime; | 719 | u8 sas_discovery_runtime; |
| 699 | u8 sas_discovery_ignore_events; | 720 | u8 sas_discovery_ignore_events; |
| 721 | |||
| 722 | /* port_info object for the host */ | ||
| 723 | struct mptsas_portinfo *hba_port_info; | ||
| 724 | u64 hba_port_sas_addr; | ||
| 725 | u16 hba_port_num_phy; | ||
| 726 | struct list_head sas_device_info_list; | ||
| 727 | struct mutex sas_device_info_mutex; | ||
| 728 | u8 old_sas_discovery_protocal; | ||
| 729 | u8 sas_discovery_quiesce_io; | ||
| 700 | int sas_index; /* index refrencing */ | 730 | int sas_index; /* index refrencing */ |
| 701 | MPT_SAS_MGMT sas_mgmt; | 731 | MPT_MGMT sas_mgmt; |
| 732 | MPT_MGMT mptbase_cmds; /* for sending config pages */ | ||
| 733 | MPT_MGMT internal_cmds; | ||
| 734 | MPT_MGMT taskmgmt_cmds; | ||
| 735 | MPT_MGMT ioctl_cmds; | ||
| 736 | spinlock_t taskmgmt_lock; /* diagnostic reset lock */ | ||
| 737 | int taskmgmt_in_progress; | ||
| 738 | u8 taskmgmt_quiesce_io; | ||
| 739 | u8 ioc_reset_in_progress; | ||
| 702 | struct work_struct sas_persist_task; | 740 | struct work_struct sas_persist_task; |
| 703 | 741 | ||
| 704 | struct work_struct fc_setup_reset_work; | 742 | struct work_struct fc_setup_reset_work; |
| @@ -707,15 +745,27 @@ typedef struct _MPT_ADAPTER | |||
| 707 | u8 fc_link_speed[2]; | 745 | u8 fc_link_speed[2]; |
| 708 | spinlock_t fc_rescan_work_lock; | 746 | spinlock_t fc_rescan_work_lock; |
| 709 | struct work_struct fc_rescan_work; | 747 | struct work_struct fc_rescan_work; |
| 710 | char fc_rescan_work_q_name[20]; | 748 | char fc_rescan_work_q_name[MPT_KOBJ_NAME_LEN]; |
| 711 | struct workqueue_struct *fc_rescan_work_q; | 749 | struct workqueue_struct *fc_rescan_work_q; |
| 750 | |||
| 751 | /* driver forced bus resets count */ | ||
| 752 | unsigned long hard_resets; | ||
| 753 | /* fw/external bus resets count */ | ||
| 754 | unsigned long soft_resets; | ||
| 755 | /* cmd timeouts */ | ||
| 756 | unsigned long timeouts; | ||
| 757 | |||
| 712 | struct scsi_cmnd **ScsiLookup; | 758 | struct scsi_cmnd **ScsiLookup; |
| 713 | spinlock_t scsi_lookup_lock; | 759 | spinlock_t scsi_lookup_lock; |
| 714 | 760 | u64 dma_mask; | |
| 715 | char reset_work_q_name[20]; | 761 | u32 broadcast_aen_busy; |
| 762 | char reset_work_q_name[MPT_KOBJ_NAME_LEN]; | ||
| 716 | struct workqueue_struct *reset_work_q; | 763 | struct workqueue_struct *reset_work_q; |
| 717 | struct delayed_work fault_reset_work; | 764 | struct delayed_work fault_reset_work; |
| 718 | spinlock_t fault_reset_work_lock; | 765 | |
| 766 | u8 sg_addr_size; | ||
| 767 | u8 in_rescan; | ||
| 768 | u8 SGE_size; | ||
| 719 | 769 | ||
| 720 | } MPT_ADAPTER; | 770 | } MPT_ADAPTER; |
| 721 | 771 | ||
| @@ -753,13 +803,14 @@ typedef struct _mpt_sge { | |||
| 753 | dma_addr_t Address; | 803 | dma_addr_t Address; |
| 754 | } MptSge_t; | 804 | } MptSge_t; |
| 755 | 805 | ||
| 756 | #define mpt_addr_size() \ | ||
| 757 | ((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SGE_FLAGS_64_BIT_ADDRESSING : \ | ||
| 758 | MPI_SGE_FLAGS_32_BIT_ADDRESSING) | ||
| 759 | 806 | ||
| 760 | #define mpt_msg_flags() \ | 807 | #define mpt_msg_flags(ioc) \ |
| 761 | ((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : \ | 808 | (ioc->sg_addr_size == sizeof(u64)) ? \ |
| 762 | MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32) | 809 | MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : \ |
| 810 | MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32 | ||
| 811 | |||
| 812 | #define MPT_SGE_FLAGS_64_BIT_ADDRESSING \ | ||
| 813 | (MPI_SGE_FLAGS_64_BIT_ADDRESSING << MPI_SGE_FLAGS_SHIFT) | ||
| 763 | 814 | ||
| 764 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 815 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 765 | /* | 816 | /* |
| @@ -835,22 +886,14 @@ typedef struct _MPT_SCSI_HOST { | |||
| 835 | /* Pool of memory for holding SCpnts before doing | 886 | /* Pool of memory for holding SCpnts before doing |
| 836 | * OS callbacks. freeQ is the free pool. | 887 | * OS callbacks. freeQ is the free pool. |
| 837 | */ | 888 | */ |
| 838 | u8 tmPending; | ||
| 839 | u8 resetPending; | ||
| 840 | u8 negoNvram; /* DV disabled, nego NVRAM */ | 889 | u8 negoNvram; /* DV disabled, nego NVRAM */ |
| 841 | u8 pad1; | 890 | u8 pad1; |
| 842 | u8 tmState; | ||
| 843 | u8 rsvd[2]; | 891 | u8 rsvd[2]; |
| 844 | MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */ | 892 | MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */ |
| 845 | struct scsi_cmnd *abortSCpnt; | 893 | struct scsi_cmnd *abortSCpnt; |
| 846 | MPT_LOCAL_REPLY localReply; /* internal cmd reply struct */ | 894 | MPT_LOCAL_REPLY localReply; /* internal cmd reply struct */ |
| 847 | unsigned long hard_resets; /* driver forced bus resets count */ | ||
| 848 | unsigned long soft_resets; /* fw/external bus resets count */ | ||
| 849 | unsigned long timeouts; /* cmd timeouts */ | ||
| 850 | ushort sel_timeout[MPT_MAX_FC_DEVICES]; | 895 | ushort sel_timeout[MPT_MAX_FC_DEVICES]; |
| 851 | char *info_kbuf; | 896 | char *info_kbuf; |
| 852 | wait_queue_head_t scandv_waitq; | ||
| 853 | int scandv_wait_done; | ||
| 854 | long last_queue_full; | 897 | long last_queue_full; |
| 855 | u16 tm_iocstatus; | 898 | u16 tm_iocstatus; |
| 856 | u16 spi_pending; | 899 | u16 spi_pending; |
| @@ -870,21 +913,16 @@ struct scsi_cmnd; | |||
| 870 | * Generic structure passed to the base mpt_config function. | 913 | * Generic structure passed to the base mpt_config function. |
| 871 | */ | 914 | */ |
| 872 | typedef struct _x_config_parms { | 915 | typedef struct _x_config_parms { |
| 873 | struct list_head linkage; /* linked list */ | ||
| 874 | struct timer_list timer; /* timer function for this request */ | ||
| 875 | union { | 916 | union { |
| 876 | ConfigExtendedPageHeader_t *ehdr; | 917 | ConfigExtendedPageHeader_t *ehdr; |
| 877 | ConfigPageHeader_t *hdr; | 918 | ConfigPageHeader_t *hdr; |
| 878 | } cfghdr; | 919 | } cfghdr; |
| 879 | dma_addr_t physAddr; | 920 | dma_addr_t physAddr; |
| 880 | int wait_done; /* wait for this request */ | ||
| 881 | u32 pageAddr; /* properly formatted */ | 921 | u32 pageAddr; /* properly formatted */ |
| 922 | u16 status; | ||
| 882 | u8 action; | 923 | u8 action; |
| 883 | u8 dir; | 924 | u8 dir; |
| 884 | u8 timeout; /* seconds */ | 925 | u8 timeout; /* seconds */ |
| 885 | u8 pad1; | ||
| 886 | u16 status; | ||
| 887 | u16 pad2; | ||
| 888 | } CONFIGPARMS; | 926 | } CONFIGPARMS; |
| 889 | 927 | ||
| 890 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 928 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| @@ -909,7 +947,6 @@ extern MPT_FRAME_HDR *mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc); | |||
| 909 | extern void mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); | 947 | extern void mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); |
| 910 | extern void mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); | 948 | extern void mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); |
| 911 | extern void mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); | 949 | extern void mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); |
| 912 | extern void mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr); | ||
| 913 | 950 | ||
| 914 | extern int mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag); | 951 | extern int mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag); |
| 915 | extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp); | 952 | extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp); |
| @@ -922,6 +959,12 @@ extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); | |||
| 922 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); | 959 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); |
| 923 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | 960 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); |
| 924 | extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk); | 961 | extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk); |
| 962 | extern int mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num, | ||
| 963 | pRaidPhysDiskPage1_t phys_disk); | ||
| 964 | extern int mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, | ||
| 965 | u8 phys_disk_num); | ||
| 966 | extern int mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc); | ||
| 967 | extern void mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc); | ||
| 925 | extern void mpt_halt_firmware(MPT_ADAPTER *ioc); | 968 | extern void mpt_halt_firmware(MPT_ADAPTER *ioc); |
| 926 | 969 | ||
| 927 | 970 | ||
| @@ -959,7 +1002,6 @@ extern int mpt_fwfault_debug; | |||
| 959 | #define MPT_SGE_FLAGS_END_OF_BUFFER (0x40000000) | 1002 | #define MPT_SGE_FLAGS_END_OF_BUFFER (0x40000000) |
| 960 | #define MPT_SGE_FLAGS_LOCAL_ADDRESS (0x08000000) | 1003 | #define MPT_SGE_FLAGS_LOCAL_ADDRESS (0x08000000) |
| 961 | #define MPT_SGE_FLAGS_DIRECTION (0x04000000) | 1004 | #define MPT_SGE_FLAGS_DIRECTION (0x04000000) |
| 962 | #define MPT_SGE_FLAGS_ADDRESSING (mpt_addr_size() << MPI_SGE_FLAGS_SHIFT) | ||
| 963 | #define MPT_SGE_FLAGS_END_OF_LIST (0x01000000) | 1005 | #define MPT_SGE_FLAGS_END_OF_LIST (0x01000000) |
| 964 | 1006 | ||
| 965 | #define MPT_SGE_FLAGS_TRANSACTION_ELEMENT (0x00000000) | 1007 | #define MPT_SGE_FLAGS_TRANSACTION_ELEMENT (0x00000000) |
| @@ -972,14 +1014,12 @@ extern int mpt_fwfault_debug; | |||
| 972 | MPT_SGE_FLAGS_END_OF_BUFFER | \ | 1014 | MPT_SGE_FLAGS_END_OF_BUFFER | \ |
| 973 | MPT_SGE_FLAGS_END_OF_LIST | \ | 1015 | MPT_SGE_FLAGS_END_OF_LIST | \ |
| 974 | MPT_SGE_FLAGS_SIMPLE_ELEMENT | \ | 1016 | MPT_SGE_FLAGS_SIMPLE_ELEMENT | \ |
| 975 | MPT_SGE_FLAGS_ADDRESSING | \ | ||
| 976 | MPT_TRANSFER_IOC_TO_HOST) | 1017 | MPT_TRANSFER_IOC_TO_HOST) |
| 977 | #define MPT_SGE_FLAGS_SSIMPLE_WRITE \ | 1018 | #define MPT_SGE_FLAGS_SSIMPLE_WRITE \ |
| 978 | (MPT_SGE_FLAGS_LAST_ELEMENT | \ | 1019 | (MPT_SGE_FLAGS_LAST_ELEMENT | \ |
| 979 | MPT_SGE_FLAGS_END_OF_BUFFER | \ | 1020 | MPT_SGE_FLAGS_END_OF_BUFFER | \ |
| 980 | MPT_SGE_FLAGS_END_OF_LIST | \ | 1021 | MPT_SGE_FLAGS_END_OF_LIST | \ |
| 981 | MPT_SGE_FLAGS_SIMPLE_ELEMENT | \ | 1022 | MPT_SGE_FLAGS_SIMPLE_ELEMENT | \ |
| 982 | MPT_SGE_FLAGS_ADDRESSING | \ | ||
| 983 | MPT_TRANSFER_HOST_TO_IOC) | 1023 | MPT_TRANSFER_HOST_TO_IOC) |
| 984 | 1024 | ||
| 985 | /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1025 | /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index c63817117c0a..9b2e2198aee9 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c | |||
| @@ -84,6 +84,7 @@ MODULE_VERSION(my_VERSION); | |||
| 84 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 84 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 85 | 85 | ||
| 86 | static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS; | 86 | static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS; |
| 87 | static u8 mptctl_taskmgmt_id = MPT_MAX_PROTOCOL_DRIVERS; | ||
| 87 | 88 | ||
| 88 | static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait ); | 89 | static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait ); |
| 89 | 90 | ||
| @@ -127,10 +128,7 @@ static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags | |||
| 127 | struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc); | 128 | struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc); |
| 128 | static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, | 129 | static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, |
| 129 | struct buflist *buflist, MPT_ADAPTER *ioc); | 130 | struct buflist *buflist, MPT_ADAPTER *ioc); |
| 130 | static void mptctl_timeout_expired (MPT_IOCTL *ioctl); | 131 | static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function); |
| 131 | static int mptctl_bus_reset(MPT_IOCTL *ioctl); | ||
| 132 | static int mptctl_set_tm_flags(MPT_SCSI_HOST *hd); | ||
| 133 | static void mptctl_free_tm_flags(MPT_ADAPTER *ioc); | ||
| 134 | 132 | ||
| 135 | /* | 133 | /* |
| 136 | * Reset Handler cleanup function | 134 | * Reset Handler cleanup function |
| @@ -183,10 +181,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock) | |||
| 183 | int rc = 0; | 181 | int rc = 0; |
| 184 | 182 | ||
| 185 | if (nonblock) { | 183 | if (nonblock) { |
| 186 | if (!mutex_trylock(&ioc->ioctl->ioctl_mutex)) | 184 | if (!mutex_trylock(&ioc->ioctl_cmds.mutex)) |
| 187 | rc = -EAGAIN; | 185 | rc = -EAGAIN; |
| 188 | } else { | 186 | } else { |
| 189 | if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex)) | 187 | if (mutex_lock_interruptible(&ioc->ioctl_cmds.mutex)) |
| 190 | rc = -ERESTARTSYS; | 188 | rc = -ERESTARTSYS; |
| 191 | } | 189 | } |
| 192 | return rc; | 190 | return rc; |
| @@ -202,99 +200,78 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock) | |||
| 202 | static int | 200 | static int |
| 203 | mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) | 201 | mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) |
| 204 | { | 202 | { |
| 205 | char *sense_data; | 203 | char *sense_data; |
| 206 | int sz, req_index; | 204 | int req_index; |
| 207 | u16 iocStatus; | 205 | int sz; |
| 208 | u8 cmd; | ||
| 209 | 206 | ||
| 210 | if (req) | 207 | if (!req) |
| 211 | cmd = req->u.hdr.Function; | 208 | return 0; |
| 212 | else | ||
| 213 | return 1; | ||
| 214 | dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tcompleting mpi function (0x%02X), req=%p, " | ||
| 215 | "reply=%p\n", ioc->name, req->u.hdr.Function, req, reply)); | ||
| 216 | |||
| 217 | if (ioc->ioctl) { | ||
| 218 | |||
| 219 | if (reply==NULL) { | ||
| 220 | |||
| 221 | dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_reply() NULL Reply " | ||
| 222 | "Function=%x!\n", ioc->name, cmd)); | ||
| 223 | 209 | ||
| 224 | ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; | 210 | dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "completing mpi function " |
| 225 | ioc->ioctl->reset &= ~MPTCTL_RESET_OK; | 211 | "(0x%02X), req=%p, reply=%p\n", ioc->name, req->u.hdr.Function, |
| 212 | req, reply)); | ||
| 226 | 213 | ||
| 227 | /* We are done, issue wake up | 214 | /* |
| 228 | */ | 215 | * Handling continuation of the same reply. Processing the first |
| 229 | ioc->ioctl->wait_done = 1; | 216 | * reply, and eating the other replys that come later. |
| 230 | wake_up (&mptctl_wait); | 217 | */ |
| 231 | return 1; | 218 | if (ioc->ioctl_cmds.msg_context != req->u.hdr.MsgContext) |
| 219 | goto out_continuation; | ||
| 232 | 220 | ||
| 233 | } | 221 | ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; |
| 234 | 222 | ||
| 235 | /* Copy the reply frame (which much exist | 223 | if (!reply) |
| 236 | * for non-SCSI I/O) to the IOC structure. | 224 | goto out; |
| 237 | */ | ||
| 238 | memcpy(ioc->ioctl->ReplyFrame, reply, | ||
| 239 | min(ioc->reply_sz, 4*reply->u.reply.MsgLength)); | ||
| 240 | ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID; | ||
| 241 | 225 | ||
| 242 | /* Set the command status to GOOD if IOC Status is GOOD | 226 | ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_RF_VALID; |
| 243 | * OR if SCSI I/O cmd and data underrun or recovered error. | 227 | sz = min(ioc->reply_sz, 4*reply->u.reply.MsgLength); |
| 244 | */ | 228 | memcpy(ioc->ioctl_cmds.reply, reply, sz); |
| 245 | iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK; | ||
| 246 | if (iocStatus == MPI_IOCSTATUS_SUCCESS) | ||
| 247 | ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; | ||
| 248 | |||
| 249 | if (iocStatus || reply->u.reply.IOCLogInfo) | ||
| 250 | dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tiocstatus (0x%04X), " | ||
| 251 | "loginfo (0x%08X)\n", ioc->name, | ||
| 252 | iocStatus, | ||
| 253 | le32_to_cpu(reply->u.reply.IOCLogInfo))); | ||
| 254 | |||
| 255 | if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || | ||
| 256 | (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { | ||
| 257 | |||
| 258 | if (reply->u.sreply.SCSIStatus || reply->u.sreply.SCSIState) | ||
| 259 | dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 260 | "\tscsi_status (0x%02x), scsi_state (0x%02x), " | ||
| 261 | "tag = (0x%04x), transfer_count (0x%08x)\n", ioc->name, | ||
| 262 | reply->u.sreply.SCSIStatus, | ||
| 263 | reply->u.sreply.SCSIState, | ||
| 264 | le16_to_cpu(reply->u.sreply.TaskTag), | ||
| 265 | le32_to_cpu(reply->u.sreply.TransferCount))); | ||
| 266 | |||
| 267 | ioc->ioctl->reset &= ~MPTCTL_RESET_OK; | ||
| 268 | |||
| 269 | if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) || | ||
| 270 | (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) { | ||
| 271 | ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; | ||
| 272 | } | ||
| 273 | } | ||
| 274 | 229 | ||
| 275 | /* Copy the sense data - if present | 230 | if (reply->u.reply.IOCStatus || reply->u.reply.IOCLogInfo) |
| 276 | */ | 231 | dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 277 | if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) && | 232 | "iocstatus (0x%04X), loginfo (0x%08X)\n", ioc->name, |
| 278 | (reply->u.sreply.SCSIState & | 233 | le16_to_cpu(reply->u.reply.IOCStatus), |
| 279 | MPI_SCSI_STATE_AUTOSENSE_VALID)){ | 234 | le32_to_cpu(reply->u.reply.IOCLogInfo))); |
| 235 | |||
| 236 | if ((req->u.hdr.Function == MPI_FUNCTION_SCSI_IO_REQUEST) || | ||
| 237 | (req->u.hdr.Function == | ||
| 238 | MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { | ||
| 239 | |||
| 240 | if (reply->u.sreply.SCSIStatus || reply->u.sreply.SCSIState) | ||
| 241 | dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 242 | "scsi_status (0x%02x), scsi_state (0x%02x), " | ||
| 243 | "tag = (0x%04x), transfer_count (0x%08x)\n", ioc->name, | ||
| 244 | reply->u.sreply.SCSIStatus, | ||
| 245 | reply->u.sreply.SCSIState, | ||
| 246 | le16_to_cpu(reply->u.sreply.TaskTag), | ||
| 247 | le32_to_cpu(reply->u.sreply.TransferCount))); | ||
| 248 | |||
| 249 | if (reply->u.sreply.SCSIState & | ||
| 250 | MPI_SCSI_STATE_AUTOSENSE_VALID) { | ||
| 280 | sz = req->u.scsireq.SenseBufferLength; | 251 | sz = req->u.scsireq.SenseBufferLength; |
| 281 | req_index = | 252 | req_index = |
| 282 | le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx); | 253 | le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx); |
| 283 | sense_data = | 254 | sense_data = ((u8 *)ioc->sense_buf_pool + |
| 284 | ((u8 *)ioc->sense_buf_pool + | ||
| 285 | (req_index * MPT_SENSE_BUFFER_ALLOC)); | 255 | (req_index * MPT_SENSE_BUFFER_ALLOC)); |
| 286 | memcpy(ioc->ioctl->sense, sense_data, sz); | 256 | memcpy(ioc->ioctl_cmds.sense, sense_data, sz); |
| 287 | ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID; | 257 | ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_SENSE_VALID; |
| 288 | } | 258 | } |
| 259 | } | ||
| 289 | 260 | ||
| 290 | if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT) | 261 | out: |
| 291 | mptctl_free_tm_flags(ioc); | 262 | /* We are done, issue wake up |
| 292 | 263 | */ | |
| 293 | /* We are done, issue wake up | 264 | if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_PENDING) { |
| 294 | */ | 265 | if (req->u.hdr.Function == MPI_FUNCTION_SCSI_TASK_MGMT) |
| 295 | ioc->ioctl->wait_done = 1; | 266 | mpt_clear_taskmgmt_in_progress_flag(ioc); |
| 296 | wake_up (&mptctl_wait); | 267 | ioc->ioctl_cmds.status &= ~MPT_MGMT_STATUS_PENDING; |
| 268 | complete(&ioc->ioctl_cmds.done); | ||
| 297 | } | 269 | } |
| 270 | |||
| 271 | out_continuation: | ||
| 272 | if (reply && (reply->u.reply.MsgFlags & | ||
| 273 | MPI_MSGFLAGS_CONTINUATION_REPLY)) | ||
| 274 | return 0; | ||
| 298 | return 1; | 275 | return 1; |
| 299 | } | 276 | } |
| 300 | 277 | ||
| @@ -304,30 +281,66 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) | |||
| 304 | * Expecting an interrupt, however timed out. | 281 | * Expecting an interrupt, however timed out. |
| 305 | * | 282 | * |
| 306 | */ | 283 | */ |
| 307 | static void mptctl_timeout_expired (MPT_IOCTL *ioctl) | 284 | static void |
| 285 | mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) | ||
| 308 | { | 286 | { |
| 309 | int rc = 1; | 287 | unsigned long flags; |
| 310 | 288 | ||
| 311 | if (ioctl == NULL) | 289 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n", |
| 312 | return; | 290 | ioc->name, __func__)); |
| 313 | dctlprintk(ioctl->ioc, | ||
| 314 | printk(MYIOC_s_DEBUG_FMT ": Timeout Expired! Host %d\n", | ||
| 315 | ioctl->ioc->name, ioctl->ioc->id)); | ||
| 316 | 291 | ||
| 317 | ioctl->wait_done = 0; | 292 | if (mpt_fwfault_debug) |
| 318 | if (ioctl->reset & MPTCTL_RESET_OK) | 293 | mpt_halt_firmware(ioc); |
| 319 | rc = mptctl_bus_reset(ioctl); | ||
| 320 | 294 | ||
| 321 | if (rc) { | 295 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
| 322 | /* Issue a reset for this device. | 296 | if (ioc->ioc_reset_in_progress) { |
| 323 | * The IOC is not responding. | 297 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); |
| 324 | */ | 298 | CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status) |
| 325 | dctlprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n", | 299 | mpt_free_msg_frame(ioc, mf); |
| 326 | ioctl->ioc->name)); | 300 | return; |
| 327 | mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP); | ||
| 328 | } | 301 | } |
| 329 | return; | 302 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); |
| 303 | |||
| 330 | 304 | ||
| 305 | if (!mptctl_bus_reset(ioc, mf->u.hdr.Function)) | ||
| 306 | return; | ||
| 307 | |||
| 308 | /* Issue a reset for this device. | ||
| 309 | * The IOC is not responding. | ||
| 310 | */ | ||
| 311 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n", | ||
| 312 | ioc->name)); | ||
| 313 | CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status) | ||
| 314 | mpt_HardResetHandler(ioc, CAN_SLEEP); | ||
| 315 | mpt_free_msg_frame(ioc, mf); | ||
| 316 | } | ||
| 317 | |||
| 318 | static int | ||
| 319 | mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | ||
| 320 | { | ||
| 321 | if (!mf) | ||
| 322 | return 0; | ||
| 323 | |||
| 324 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 325 | "TaskMgmt completed (mf=%p, mr=%p)\n", | ||
| 326 | ioc->name, mf, mr)); | ||
| 327 | |||
| 328 | ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; | ||
| 329 | |||
| 330 | if (!mr) | ||
| 331 | goto out; | ||
| 332 | |||
| 333 | ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID; | ||
| 334 | memcpy(ioc->taskmgmt_cmds.reply, mr, | ||
| 335 | min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength)); | ||
| 336 | out: | ||
| 337 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) { | ||
| 338 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
| 339 | ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING; | ||
| 340 | complete(&ioc->taskmgmt_cmds.done); | ||
| 341 | return 1; | ||
| 342 | } | ||
| 343 | return 0; | ||
| 331 | } | 344 | } |
| 332 | 345 | ||
| 333 | /* mptctl_bus_reset | 346 | /* mptctl_bus_reset |
| @@ -335,133 +348,150 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl) | |||
| 335 | * Bus reset code. | 348 | * Bus reset code. |
| 336 | * | 349 | * |
| 337 | */ | 350 | */ |
| 338 | static int mptctl_bus_reset(MPT_IOCTL *ioctl) | 351 | static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) |
| 339 | { | 352 | { |
| 340 | MPT_FRAME_HDR *mf; | 353 | MPT_FRAME_HDR *mf; |
| 341 | SCSITaskMgmt_t *pScsiTm; | 354 | SCSITaskMgmt_t *pScsiTm; |
| 342 | MPT_SCSI_HOST *hd; | 355 | SCSITaskMgmtReply_t *pScsiTmReply; |
| 343 | int ii; | 356 | int ii; |
| 344 | int retval=0; | 357 | int retval; |
| 345 | 358 | unsigned long timeout; | |
| 346 | 359 | unsigned long time_count; | |
| 347 | ioctl->reset &= ~MPTCTL_RESET_OK; | 360 | u16 iocstatus; |
| 348 | 361 | ||
| 349 | if (ioctl->ioc->sh == NULL) | 362 | /* bus reset is only good for SCSI IO, RAID PASSTHRU */ |
| 363 | if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) || | ||
| 364 | (function == MPI_FUNCTION_SCSI_IO_REQUEST)) { | ||
| 365 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT | ||
| 366 | "TaskMgmt, not SCSI_IO!!\n", ioc->name)); | ||
| 350 | return -EPERM; | 367 | return -EPERM; |
| 368 | } | ||
| 351 | 369 | ||
| 352 | hd = shost_priv(ioctl->ioc->sh); | 370 | mutex_lock(&ioc->taskmgmt_cmds.mutex); |
| 353 | if (hd == NULL) | 371 | if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { |
| 372 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | ||
| 354 | return -EPERM; | 373 | return -EPERM; |
| 374 | } | ||
| 355 | 375 | ||
| 356 | /* Single threading .... | 376 | retval = 0; |
| 357 | */ | ||
| 358 | if (mptctl_set_tm_flags(hd) != 0) | ||
| 359 | return -EPERM; | ||
| 360 | 377 | ||
| 361 | /* Send request | 378 | /* Send request |
| 362 | */ | 379 | */ |
| 363 | if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc)) == NULL) { | 380 | mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc); |
| 364 | dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt, no msg frames!!\n", | 381 | if (mf == NULL) { |
| 365 | ioctl->ioc->name)); | 382 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT |
| 366 | 383 | "TaskMgmt, no msg frames!!\n", ioc->name)); | |
| 367 | mptctl_free_tm_flags(ioctl->ioc); | 384 | mpt_clear_taskmgmt_in_progress_flag(ioc); |
| 368 | return -ENOMEM; | 385 | retval = -ENOMEM; |
| 386 | goto mptctl_bus_reset_done; | ||
| 369 | } | 387 | } |
| 370 | 388 | ||
| 371 | dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n", | 389 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n", |
| 372 | ioctl->ioc->name, mf)); | 390 | ioc->name, mf)); |
| 373 | 391 | ||
| 374 | pScsiTm = (SCSITaskMgmt_t *) mf; | 392 | pScsiTm = (SCSITaskMgmt_t *) mf; |
| 375 | pScsiTm->TargetID = ioctl->id; | 393 | memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t)); |
| 376 | pScsiTm->Bus = hd->port; /* 0 */ | ||
| 377 | pScsiTm->ChainOffset = 0; | ||
| 378 | pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; | 394 | pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; |
| 379 | pScsiTm->Reserved = 0; | ||
| 380 | pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; | 395 | pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; |
| 381 | pScsiTm->Reserved1 = 0; | ||
| 382 | pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; | 396 | pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; |
| 383 | 397 | pScsiTm->TargetID = 0; | |
| 398 | pScsiTm->Bus = 0; | ||
| 399 | pScsiTm->ChainOffset = 0; | ||
| 400 | pScsiTm->Reserved = 0; | ||
| 401 | pScsiTm->Reserved1 = 0; | ||
| 402 | pScsiTm->TaskMsgContext = 0; | ||
| 384 | for (ii= 0; ii < 8; ii++) | 403 | for (ii= 0; ii < 8; ii++) |
| 385 | pScsiTm->LUN[ii] = 0; | 404 | pScsiTm->LUN[ii] = 0; |
| 386 | |||
| 387 | for (ii=0; ii < 7; ii++) | 405 | for (ii=0; ii < 7; ii++) |
| 388 | pScsiTm->Reserved2[ii] = 0; | 406 | pScsiTm->Reserved2[ii] = 0; |
| 389 | 407 | ||
| 390 | pScsiTm->TaskMsgContext = 0; | 408 | switch (ioc->bus_type) { |
| 391 | dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT | 409 | case FC: |
| 392 | "mptctl_bus_reset: issued.\n", ioctl->ioc->name)); | 410 | timeout = 40; |
| 393 | 411 | break; | |
| 394 | DBG_DUMP_TM_REQUEST_FRAME(ioctl->ioc, (u32 *)mf); | 412 | case SAS: |
| 413 | timeout = 30; | ||
| 414 | break; | ||
| 415 | case SPI: | ||
| 416 | default: | ||
| 417 | timeout = 2; | ||
| 418 | break; | ||
| 419 | } | ||
| 395 | 420 | ||
| 396 | ioctl->wait_done=0; | 421 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 422 | "TaskMgmt type=%d timeout=%ld\n", | ||
| 423 | ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout)); | ||
| 397 | 424 | ||
| 398 | if ((ioctl->ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && | 425 | INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status) |
| 399 | (ioctl->ioc->facts.MsgVersion >= MPI_VERSION_01_05)) | 426 | CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) |
| 400 | mpt_put_msg_frame_hi_pri(mptctl_id, ioctl->ioc, mf); | 427 | time_count = jiffies; |
| 428 | if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && | ||
| 429 | (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) | ||
| 430 | mpt_put_msg_frame_hi_pri(mptctl_taskmgmt_id, ioc, mf); | ||
| 401 | else { | 431 | else { |
| 402 | retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc, | 432 | retval = mpt_send_handshake_request(mptctl_taskmgmt_id, ioc, |
| 403 | sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); | 433 | sizeof(SCSITaskMgmt_t), (u32 *)pScsiTm, CAN_SLEEP); |
| 404 | if (retval != 0) { | 434 | if (retval != 0) { |
| 405 | dfailprintk(ioctl->ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!" | 435 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 406 | " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, | 436 | "TaskMgmt send_handshake FAILED!" |
| 407 | hd->ioc, mf)); | 437 | " (ioc %p, mf %p, rc=%d) \n", ioc->name, |
| 438 | ioc, mf, retval)); | ||
| 439 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
| 408 | goto mptctl_bus_reset_done; | 440 | goto mptctl_bus_reset_done; |
| 409 | } | 441 | } |
| 410 | } | 442 | } |
| 411 | 443 | ||
| 412 | /* Now wait for the command to complete */ | 444 | /* Now wait for the command to complete */ |
| 413 | ii = wait_event_timeout(mptctl_wait, | 445 | ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ); |
| 414 | ioctl->wait_done == 1, | 446 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { |
| 415 | HZ*5 /* 5 second timeout */); | 447 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 448 | "TaskMgmt failed\n", ioc->name)); | ||
| 449 | mpt_free_msg_frame(ioc, mf); | ||
| 450 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
| 451 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) | ||
| 452 | retval = 0; | ||
| 453 | else | ||
| 454 | retval = -1; /* return failure */ | ||
| 455 | goto mptctl_bus_reset_done; | ||
| 456 | } | ||
| 416 | 457 | ||
| 417 | if(ii <=0 && (ioctl->wait_done != 1 )) { | 458 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { |
| 418 | mpt_free_msg_frame(hd->ioc, mf); | 459 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 419 | ioctl->wait_done = 0; | 460 | "TaskMgmt failed\n", ioc->name)); |
| 461 | retval = -1; /* return failure */ | ||
| 462 | goto mptctl_bus_reset_done; | ||
| 463 | } | ||
| 464 | |||
| 465 | pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply; | ||
| 466 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 467 | "TaskMgmt fw_channel = %d, fw_id = %d, task_type=0x%02X, " | ||
| 468 | "iocstatus=0x%04X\n\tloginfo=0x%08X, response_code=0x%02X, " | ||
| 469 | "term_cmnds=%d\n", ioc->name, pScsiTmReply->Bus, | ||
| 470 | pScsiTmReply->TargetID, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | ||
| 471 | le16_to_cpu(pScsiTmReply->IOCStatus), | ||
| 472 | le32_to_cpu(pScsiTmReply->IOCLogInfo), | ||
| 473 | pScsiTmReply->ResponseCode, | ||
| 474 | le32_to_cpu(pScsiTmReply->TerminationCount))); | ||
| 475 | |||
| 476 | iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
| 477 | |||
| 478 | if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || | ||
| 479 | iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED || | ||
| 480 | iocstatus == MPI_IOCSTATUS_SUCCESS) | ||
| 481 | retval = 0; | ||
| 482 | else { | ||
| 483 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 484 | "TaskMgmt failed\n", ioc->name)); | ||
| 420 | retval = -1; /* return failure */ | 485 | retval = -1; /* return failure */ |
| 421 | } | 486 | } |
| 422 | 487 | ||
| 423 | mptctl_bus_reset_done: | ||
| 424 | 488 | ||
| 425 | mptctl_free_tm_flags(ioctl->ioc); | 489 | mptctl_bus_reset_done: |
| 490 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | ||
| 491 | CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) | ||
| 426 | return retval; | 492 | return retval; |
| 427 | } | 493 | } |
| 428 | 494 | ||
| 429 | static int | ||
| 430 | mptctl_set_tm_flags(MPT_SCSI_HOST *hd) { | ||
| 431 | unsigned long flags; | ||
| 432 | |||
| 433 | spin_lock_irqsave(&hd->ioc->FreeQlock, flags); | ||
| 434 | |||
| 435 | if (hd->tmState == TM_STATE_NONE) { | ||
| 436 | hd->tmState = TM_STATE_IN_PROGRESS; | ||
| 437 | hd->tmPending = 1; | ||
| 438 | spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); | ||
| 439 | } else { | ||
| 440 | spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); | ||
| 441 | return -EBUSY; | ||
| 442 | } | ||
| 443 | |||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | |||
| 447 | static void | ||
| 448 | mptctl_free_tm_flags(MPT_ADAPTER *ioc) | ||
| 449 | { | ||
| 450 | MPT_SCSI_HOST * hd; | ||
| 451 | unsigned long flags; | ||
| 452 | |||
| 453 | hd = shost_priv(ioc->sh); | ||
| 454 | if (hd == NULL) | ||
| 455 | return; | ||
| 456 | |||
| 457 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
| 458 | |||
| 459 | hd->tmState = TM_STATE_NONE; | ||
| 460 | hd->tmPending = 0; | ||
| 461 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
| 462 | |||
| 463 | return; | ||
| 464 | } | ||
| 465 | 495 | ||
| 466 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 496 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 467 | /* mptctl_ioc_reset | 497 | /* mptctl_ioc_reset |
| @@ -473,22 +503,23 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc) | |||
| 473 | static int | 503 | static int |
| 474 | mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | 504 | mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) |
| 475 | { | 505 | { |
| 476 | MPT_IOCTL *ioctl = ioc->ioctl; | ||
| 477 | dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC %s_reset routed to IOCTL driver!\n", ioc->name, | ||
| 478 | reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( | ||
| 479 | reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); | ||
| 480 | |||
| 481 | if(ioctl == NULL) | ||
| 482 | return 1; | ||
| 483 | |||
| 484 | switch(reset_phase) { | 506 | switch(reset_phase) { |
| 485 | case MPT_IOC_SETUP_RESET: | 507 | case MPT_IOC_SETUP_RESET: |
| 486 | ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET; | 508 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 509 | "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__)); | ||
| 510 | break; | ||
| 511 | case MPT_IOC_PRE_RESET: | ||
| 512 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 513 | "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__)); | ||
| 487 | break; | 514 | break; |
| 488 | case MPT_IOC_POST_RESET: | 515 | case MPT_IOC_POST_RESET: |
| 489 | ioctl->status &= ~MPT_IOCTL_STATUS_DID_IOCRESET; | 516 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 517 | "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__)); | ||
| 518 | if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_PENDING) { | ||
| 519 | ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_DID_IOCRESET; | ||
| 520 | complete(&ioc->ioctl_cmds.done); | ||
| 521 | } | ||
| 490 | break; | 522 | break; |
| 491 | case MPT_IOC_PRE_RESET: | ||
| 492 | default: | 523 | default: |
| 493 | break; | 524 | break; |
| 494 | } | 525 | } |
| @@ -642,7 +673,7 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 642 | else | 673 | else |
| 643 | ret = -EINVAL; | 674 | ret = -EINVAL; |
| 644 | 675 | ||
| 645 | mutex_unlock(&iocp->ioctl->ioctl_mutex); | 676 | mutex_unlock(&iocp->ioctl_cmds.mutex); |
| 646 | 677 | ||
| 647 | return ret; | 678 | return ret; |
| 648 | } | 679 | } |
| @@ -758,6 +789,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
| 758 | int sge_offset = 0; | 789 | int sge_offset = 0; |
| 759 | u16 iocstat; | 790 | u16 iocstat; |
| 760 | pFWDownloadReply_t ReplyMsg = NULL; | 791 | pFWDownloadReply_t ReplyMsg = NULL; |
| 792 | unsigned long timeleft; | ||
| 761 | 793 | ||
| 762 | if (mpt_verify_adapter(ioc, &iocp) < 0) { | 794 | if (mpt_verify_adapter(ioc, &iocp) < 0) { |
| 763 | printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n", | 795 | printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n", |
| @@ -841,8 +873,9 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
| 841 | * 96 8 | 873 | * 96 8 |
| 842 | * 64 4 | 874 | * 64 4 |
| 843 | */ | 875 | */ |
| 844 | maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t)) | 876 | maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - |
| 845 | / (sizeof(dma_addr_t) + sizeof(u32)); | 877 | sizeof(FWDownloadTCSGE_t)) |
| 878 | / iocp->SGE_size; | ||
| 846 | if (numfrags > maxfrags) { | 879 | if (numfrags > maxfrags) { |
| 847 | ret = -EMLINK; | 880 | ret = -EMLINK; |
| 848 | goto fwdl_out; | 881 | goto fwdl_out; |
| @@ -870,7 +903,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
| 870 | if (nib == 0 || nib == 3) { | 903 | if (nib == 0 || nib == 3) { |
| 871 | ; | 904 | ; |
| 872 | } else if (sgIn->Address) { | 905 | } else if (sgIn->Address) { |
| 873 | mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address); | 906 | iocp->add_sge(sgOut, sgIn->FlagsLength, sgIn->Address); |
| 874 | n++; | 907 | n++; |
| 875 | if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) { | 908 | if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) { |
| 876 | printk(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - " | 909 | printk(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - " |
| @@ -882,7 +915,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
| 882 | } | 915 | } |
| 883 | sgIn++; | 916 | sgIn++; |
| 884 | bl++; | 917 | bl++; |
| 885 | sgOut += (sizeof(dma_addr_t) + sizeof(u32)); | 918 | sgOut += iocp->SGE_size; |
| 886 | } | 919 | } |
| 887 | 920 | ||
| 888 | DBG_DUMP_FW_DOWNLOAD(iocp, (u32 *)mf, numfrags); | 921 | DBG_DUMP_FW_DOWNLOAD(iocp, (u32 *)mf, numfrags); |
| @@ -891,16 +924,30 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
| 891 | * Finally, perform firmware download. | 924 | * Finally, perform firmware download. |
| 892 | */ | 925 | */ |
| 893 | ReplyMsg = NULL; | 926 | ReplyMsg = NULL; |
| 927 | SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, dlmsg->MsgContext); | ||
| 928 | INITIALIZE_MGMT_STATUS(iocp->ioctl_cmds.status) | ||
| 894 | mpt_put_msg_frame(mptctl_id, iocp, mf); | 929 | mpt_put_msg_frame(mptctl_id, iocp, mf); |
| 895 | 930 | ||
| 896 | /* Now wait for the command to complete */ | 931 | /* Now wait for the command to complete */ |
| 897 | ret = wait_event_timeout(mptctl_wait, | 932 | retry_wait: |
| 898 | iocp->ioctl->wait_done == 1, | 933 | timeleft = wait_for_completion_timeout(&iocp->ioctl_cmds.done, HZ*60); |
| 899 | HZ*60); | 934 | if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { |
| 935 | ret = -ETIME; | ||
| 936 | printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __func__); | ||
| 937 | if (iocp->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) { | ||
| 938 | mpt_free_msg_frame(iocp, mf); | ||
| 939 | goto fwdl_out; | ||
| 940 | } | ||
| 941 | if (!timeleft) | ||
| 942 | mptctl_timeout_expired(iocp, mf); | ||
| 943 | else | ||
| 944 | goto retry_wait; | ||
| 945 | goto fwdl_out; | ||
| 946 | } | ||
| 900 | 947 | ||
| 901 | if(ret <=0 && (iocp->ioctl->wait_done != 1 )) { | 948 | if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { |
| 902 | /* Now we need to reset the board */ | 949 | printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __func__); |
| 903 | mptctl_timeout_expired(iocp->ioctl); | 950 | mpt_free_msg_frame(iocp, mf); |
| 904 | ret = -ENODATA; | 951 | ret = -ENODATA; |
| 905 | goto fwdl_out; | 952 | goto fwdl_out; |
| 906 | } | 953 | } |
| @@ -908,7 +955,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
| 908 | if (sgl) | 955 | if (sgl) |
| 909 | kfree_sgl(sgl, sgl_dma, buflist, iocp); | 956 | kfree_sgl(sgl, sgl_dma, buflist, iocp); |
| 910 | 957 | ||
| 911 | ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame; | 958 | ReplyMsg = (pFWDownloadReply_t)iocp->ioctl_cmds.reply; |
| 912 | iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK; | 959 | iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK; |
| 913 | if (iocstat == MPI_IOCSTATUS_SUCCESS) { | 960 | if (iocstat == MPI_IOCSTATUS_SUCCESS) { |
| 914 | printk(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name); | 961 | printk(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name); |
| @@ -932,6 +979,9 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
| 932 | return 0; | 979 | return 0; |
| 933 | 980 | ||
| 934 | fwdl_out: | 981 | fwdl_out: |
| 982 | |||
| 983 | CLEAR_MGMT_STATUS(iocp->ioctl_cmds.status); | ||
| 984 | SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, 0); | ||
| 935 | kfree_sgl(sgl, sgl_dma, buflist, iocp); | 985 | kfree_sgl(sgl, sgl_dma, buflist, iocp); |
| 936 | return ret; | 986 | return ret; |
| 937 | } | 987 | } |
| @@ -1003,7 +1053,7 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, | |||
| 1003 | * | 1053 | * |
| 1004 | */ | 1054 | */ |
| 1005 | sgl = sglbuf; | 1055 | sgl = sglbuf; |
| 1006 | sg_spill = ((ioc->req_sz - sge_offset)/(sizeof(dma_addr_t) + sizeof(u32))) - 1; | 1056 | sg_spill = ((ioc->req_sz - sge_offset)/ioc->SGE_size) - 1; |
| 1007 | while (bytes_allocd < bytes) { | 1057 | while (bytes_allocd < bytes) { |
| 1008 | this_alloc = min(alloc_sz, bytes-bytes_allocd); | 1058 | this_alloc = min(alloc_sz, bytes-bytes_allocd); |
| 1009 | buflist[buflist_ent].len = this_alloc; | 1059 | buflist[buflist_ent].len = this_alloc; |
| @@ -1024,8 +1074,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, | |||
| 1024 | dma_addr_t dma_addr; | 1074 | dma_addr_t dma_addr; |
| 1025 | 1075 | ||
| 1026 | bytes_allocd += this_alloc; | 1076 | bytes_allocd += this_alloc; |
| 1027 | sgl->FlagsLength = (0x10000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|this_alloc); | 1077 | sgl->FlagsLength = (0x10000000|sgdir|this_alloc); |
| 1028 | dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir); | 1078 | dma_addr = pci_map_single(ioc->pcidev, |
| 1079 | buflist[buflist_ent].kptr, this_alloc, dir); | ||
| 1029 | sgl->Address = dma_addr; | 1080 | sgl->Address = dma_addr; |
| 1030 | 1081 | ||
| 1031 | fragcnt++; | 1082 | fragcnt++; |
| @@ -1771,7 +1822,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 1771 | int msgContext; | 1822 | int msgContext; |
| 1772 | u16 req_idx; | 1823 | u16 req_idx; |
| 1773 | ulong timeout; | 1824 | ulong timeout; |
| 1825 | unsigned long timeleft; | ||
| 1774 | struct scsi_device *sdev; | 1826 | struct scsi_device *sdev; |
| 1827 | unsigned long flags; | ||
| 1828 | u8 function; | ||
| 1775 | 1829 | ||
| 1776 | /* bufIn and bufOut are used for user to kernel space transfers | 1830 | /* bufIn and bufOut are used for user to kernel space transfers |
| 1777 | */ | 1831 | */ |
| @@ -1784,24 +1838,23 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 1784 | __FILE__, __LINE__, iocnum); | 1838 | __FILE__, __LINE__, iocnum); |
| 1785 | return -ENODEV; | 1839 | return -ENODEV; |
| 1786 | } | 1840 | } |
| 1787 | if (!ioc->ioctl) { | 1841 | |
| 1788 | printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - " | 1842 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
| 1789 | "No memory available during driver init.\n", | 1843 | if (ioc->ioc_reset_in_progress) { |
| 1790 | __FILE__, __LINE__); | 1844 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); |
| 1791 | return -ENOMEM; | ||
| 1792 | } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) { | ||
| 1793 | printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - " | 1845 | printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - " |
| 1794 | "Busy with IOC Reset \n", __FILE__, __LINE__); | 1846 | "Busy with diagnostic reset\n", __FILE__, __LINE__); |
| 1795 | return -EBUSY; | 1847 | return -EBUSY; |
| 1796 | } | 1848 | } |
| 1849 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 1797 | 1850 | ||
| 1798 | /* Verify that the final request frame will not be too large. | 1851 | /* Verify that the final request frame will not be too large. |
| 1799 | */ | 1852 | */ |
| 1800 | sz = karg.dataSgeOffset * 4; | 1853 | sz = karg.dataSgeOffset * 4; |
| 1801 | if (karg.dataInSize > 0) | 1854 | if (karg.dataInSize > 0) |
| 1802 | sz += sizeof(dma_addr_t) + sizeof(u32); | 1855 | sz += ioc->SGE_size; |
| 1803 | if (karg.dataOutSize > 0) | 1856 | if (karg.dataOutSize > 0) |
| 1804 | sz += sizeof(dma_addr_t) + sizeof(u32); | 1857 | sz += ioc->SGE_size; |
| 1805 | 1858 | ||
| 1806 | if (sz > ioc->req_sz) { | 1859 | if (sz > ioc->req_sz) { |
| 1807 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " | 1860 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " |
| @@ -1827,10 +1880,12 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 1827 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " | 1880 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " |
| 1828 | "Unable to read MF from mpt_ioctl_command struct @ %p\n", | 1881 | "Unable to read MF from mpt_ioctl_command struct @ %p\n", |
| 1829 | ioc->name, __FILE__, __LINE__, mfPtr); | 1882 | ioc->name, __FILE__, __LINE__, mfPtr); |
| 1883 | function = -1; | ||
| 1830 | rc = -EFAULT; | 1884 | rc = -EFAULT; |
| 1831 | goto done_free_mem; | 1885 | goto done_free_mem; |
| 1832 | } | 1886 | } |
| 1833 | hdr->MsgContext = cpu_to_le32(msgContext); | 1887 | hdr->MsgContext = cpu_to_le32(msgContext); |
| 1888 | function = hdr->Function; | ||
| 1834 | 1889 | ||
| 1835 | 1890 | ||
| 1836 | /* Verify that this request is allowed. | 1891 | /* Verify that this request is allowed. |
| @@ -1838,7 +1893,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 1838 | dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sending mpi function (0x%02X), req=%p\n", | 1893 | dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sending mpi function (0x%02X), req=%p\n", |
| 1839 | ioc->name, hdr->Function, mf)); | 1894 | ioc->name, hdr->Function, mf)); |
| 1840 | 1895 | ||
| 1841 | switch (hdr->Function) { | 1896 | switch (function) { |
| 1842 | case MPI_FUNCTION_IOC_FACTS: | 1897 | case MPI_FUNCTION_IOC_FACTS: |
| 1843 | case MPI_FUNCTION_PORT_FACTS: | 1898 | case MPI_FUNCTION_PORT_FACTS: |
| 1844 | karg.dataOutSize = karg.dataInSize = 0; | 1899 | karg.dataOutSize = karg.dataInSize = 0; |
| @@ -1893,7 +1948,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 1893 | } | 1948 | } |
| 1894 | 1949 | ||
| 1895 | pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; | 1950 | pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; |
| 1896 | pScsiReq->MsgFlags |= mpt_msg_flags(); | 1951 | pScsiReq->MsgFlags |= mpt_msg_flags(ioc); |
| 1897 | 1952 | ||
| 1898 | 1953 | ||
| 1899 | /* verify that app has not requested | 1954 | /* verify that app has not requested |
| @@ -1935,8 +1990,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 1935 | pScsiReq->Control = cpu_to_le32(scsidir | qtag); | 1990 | pScsiReq->Control = cpu_to_le32(scsidir | qtag); |
| 1936 | pScsiReq->DataLength = cpu_to_le32(dataSize); | 1991 | pScsiReq->DataLength = cpu_to_le32(dataSize); |
| 1937 | 1992 | ||
| 1938 | ioc->ioctl->reset = MPTCTL_RESET_OK; | ||
| 1939 | ioc->ioctl->id = pScsiReq->TargetID; | ||
| 1940 | 1993 | ||
| 1941 | } else { | 1994 | } else { |
| 1942 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " | 1995 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " |
| @@ -1979,7 +2032,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 1979 | int dataSize; | 2032 | int dataSize; |
| 1980 | 2033 | ||
| 1981 | pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; | 2034 | pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; |
| 1982 | pScsiReq->MsgFlags |= mpt_msg_flags(); | 2035 | pScsiReq->MsgFlags |= mpt_msg_flags(ioc); |
| 1983 | 2036 | ||
| 1984 | 2037 | ||
| 1985 | /* verify that app has not requested | 2038 | /* verify that app has not requested |
| @@ -2014,8 +2067,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 2014 | pScsiReq->Control = cpu_to_le32(scsidir | qtag); | 2067 | pScsiReq->Control = cpu_to_le32(scsidir | qtag); |
| 2015 | pScsiReq->DataLength = cpu_to_le32(dataSize); | 2068 | pScsiReq->DataLength = cpu_to_le32(dataSize); |
| 2016 | 2069 | ||
| 2017 | ioc->ioctl->reset = MPTCTL_RESET_OK; | ||
| 2018 | ioc->ioctl->id = pScsiReq->TargetID; | ||
| 2019 | } else { | 2070 | } else { |
| 2020 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " | 2071 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " |
| 2021 | "SCSI driver is not loaded. \n", | 2072 | "SCSI driver is not loaded. \n", |
| @@ -2026,20 +2077,17 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 2026 | break; | 2077 | break; |
| 2027 | 2078 | ||
| 2028 | case MPI_FUNCTION_SCSI_TASK_MGMT: | 2079 | case MPI_FUNCTION_SCSI_TASK_MGMT: |
| 2029 | { | 2080 | { |
| 2030 | MPT_SCSI_HOST *hd = NULL; | 2081 | SCSITaskMgmt_t *pScsiTm; |
| 2031 | if ((ioc->sh == NULL) || ((hd = shost_priv(ioc->sh)) == NULL)) { | 2082 | pScsiTm = (SCSITaskMgmt_t *)mf; |
| 2032 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " | 2083 | dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2033 | "SCSI driver not loaded or SCSI host not found. \n", | 2084 | "\tTaskType=0x%x MsgFlags=0x%x " |
| 2034 | ioc->name, __FILE__, __LINE__); | 2085 | "TaskMsgContext=0x%x id=%d channel=%d\n", |
| 2035 | rc = -EFAULT; | 2086 | ioc->name, pScsiTm->TaskType, le32_to_cpu |
| 2036 | goto done_free_mem; | 2087 | (pScsiTm->TaskMsgContext), pScsiTm->MsgFlags, |
| 2037 | } else if (mptctl_set_tm_flags(hd) != 0) { | 2088 | pScsiTm->TargetID, pScsiTm->Bus)); |
| 2038 | rc = -EPERM; | ||
| 2039 | goto done_free_mem; | ||
| 2040 | } | ||
| 2041 | } | ||
| 2042 | break; | 2089 | break; |
| 2090 | } | ||
| 2043 | 2091 | ||
| 2044 | case MPI_FUNCTION_IOC_INIT: | 2092 | case MPI_FUNCTION_IOC_INIT: |
| 2045 | { | 2093 | { |
| @@ -2123,8 +2171,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 2123 | if (karg.dataInSize > 0) { | 2171 | if (karg.dataInSize > 0) { |
| 2124 | flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | | 2172 | flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | |
| 2125 | MPI_SGE_FLAGS_END_OF_BUFFER | | 2173 | MPI_SGE_FLAGS_END_OF_BUFFER | |
| 2126 | MPI_SGE_FLAGS_DIRECTION | | 2174 | MPI_SGE_FLAGS_DIRECTION) |
| 2127 | mpt_addr_size() ) | ||
| 2128 | << MPI_SGE_FLAGS_SHIFT; | 2175 | << MPI_SGE_FLAGS_SHIFT; |
| 2129 | } else { | 2176 | } else { |
| 2130 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; | 2177 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; |
| @@ -2141,8 +2188,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 2141 | /* Set up this SGE. | 2188 | /* Set up this SGE. |
| 2142 | * Copy to MF and to sglbuf | 2189 | * Copy to MF and to sglbuf |
| 2143 | */ | 2190 | */ |
| 2144 | mpt_add_sge(psge, flagsLength, dma_addr_out); | 2191 | ioc->add_sge(psge, flagsLength, dma_addr_out); |
| 2145 | psge += (sizeof(u32) + sizeof(dma_addr_t)); | 2192 | psge += ioc->SGE_size; |
| 2146 | 2193 | ||
| 2147 | /* Copy user data to kernel space. | 2194 | /* Copy user data to kernel space. |
| 2148 | */ | 2195 | */ |
| @@ -2175,18 +2222,25 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 2175 | /* Set up this SGE | 2222 | /* Set up this SGE |
| 2176 | * Copy to MF and to sglbuf | 2223 | * Copy to MF and to sglbuf |
| 2177 | */ | 2224 | */ |
| 2178 | mpt_add_sge(psge, flagsLength, dma_addr_in); | 2225 | ioc->add_sge(psge, flagsLength, dma_addr_in); |
| 2179 | } | 2226 | } |
| 2180 | } | 2227 | } |
| 2181 | } else { | 2228 | } else { |
| 2182 | /* Add a NULL SGE | 2229 | /* Add a NULL SGE |
| 2183 | */ | 2230 | */ |
| 2184 | mpt_add_sge(psge, flagsLength, (dma_addr_t) -1); | 2231 | ioc->add_sge(psge, flagsLength, (dma_addr_t) -1); |
| 2185 | } | 2232 | } |
| 2186 | 2233 | ||
| 2187 | ioc->ioctl->wait_done = 0; | 2234 | SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, hdr->MsgContext); |
| 2235 | INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status) | ||
| 2188 | if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) { | 2236 | if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) { |
| 2189 | 2237 | ||
| 2238 | mutex_lock(&ioc->taskmgmt_cmds.mutex); | ||
| 2239 | if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { | ||
| 2240 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | ||
| 2241 | goto done_free_mem; | ||
| 2242 | } | ||
| 2243 | |||
| 2190 | DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); | 2244 | DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); |
| 2191 | 2245 | ||
| 2192 | if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && | 2246 | if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && |
| @@ -2197,10 +2251,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 2197 | sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP); | 2251 | sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP); |
| 2198 | if (rc != 0) { | 2252 | if (rc != 0) { |
| 2199 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 2253 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 2200 | "_send_handshake FAILED! (ioc %p, mf %p)\n", | 2254 | "send_handshake FAILED! (ioc %p, mf %p)\n", |
| 2201 | ioc->name, ioc, mf)); | 2255 | ioc->name, ioc, mf)); |
| 2202 | mptctl_free_tm_flags(ioc); | 2256 | mpt_clear_taskmgmt_in_progress_flag(ioc); |
| 2203 | rc = -ENODATA; | 2257 | rc = -ENODATA; |
| 2258 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | ||
| 2204 | goto done_free_mem; | 2259 | goto done_free_mem; |
| 2205 | } | 2260 | } |
| 2206 | } | 2261 | } |
| @@ -2210,36 +2265,47 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 2210 | 2265 | ||
| 2211 | /* Now wait for the command to complete */ | 2266 | /* Now wait for the command to complete */ |
| 2212 | timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; | 2267 | timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; |
| 2213 | timeout = wait_event_timeout(mptctl_wait, | 2268 | retry_wait: |
| 2214 | ioc->ioctl->wait_done == 1, | 2269 | timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done, |
| 2215 | HZ*timeout); | 2270 | HZ*timeout); |
| 2216 | 2271 | if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | |
| 2217 | if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) { | 2272 | rc = -ETIME; |
| 2218 | /* Now we need to reset the board */ | 2273 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: TIMED OUT!\n", |
| 2219 | 2274 | ioc->name, __func__)); | |
| 2220 | if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) | 2275 | if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) { |
| 2221 | mptctl_free_tm_flags(ioc); | 2276 | if (function == MPI_FUNCTION_SCSI_TASK_MGMT) |
| 2222 | 2277 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | |
| 2223 | mptctl_timeout_expired(ioc->ioctl); | 2278 | goto done_free_mem; |
| 2224 | rc = -ENODATA; | 2279 | } |
| 2280 | if (!timeleft) { | ||
| 2281 | if (function == MPI_FUNCTION_SCSI_TASK_MGMT) | ||
| 2282 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | ||
| 2283 | mptctl_timeout_expired(ioc, mf); | ||
| 2284 | mf = NULL; | ||
| 2285 | } else | ||
| 2286 | goto retry_wait; | ||
| 2225 | goto done_free_mem; | 2287 | goto done_free_mem; |
| 2226 | } | 2288 | } |
| 2227 | 2289 | ||
| 2290 | if (function == MPI_FUNCTION_SCSI_TASK_MGMT) | ||
| 2291 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | ||
| 2292 | |||
| 2293 | |||
| 2228 | mf = NULL; | 2294 | mf = NULL; |
| 2229 | 2295 | ||
| 2230 | /* If a valid reply frame, copy to the user. | 2296 | /* If a valid reply frame, copy to the user. |
| 2231 | * Offset 2: reply length in U32's | 2297 | * Offset 2: reply length in U32's |
| 2232 | */ | 2298 | */ |
| 2233 | if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) { | 2299 | if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) { |
| 2234 | if (karg.maxReplyBytes < ioc->reply_sz) { | 2300 | if (karg.maxReplyBytes < ioc->reply_sz) { |
| 2235 | sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]); | 2301 | sz = min(karg.maxReplyBytes, |
| 2302 | 4*ioc->ioctl_cmds.reply[2]); | ||
| 2236 | } else { | 2303 | } else { |
| 2237 | sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]); | 2304 | sz = min(ioc->reply_sz, 4*ioc->ioctl_cmds.reply[2]); |
| 2238 | } | 2305 | } |
| 2239 | |||
| 2240 | if (sz > 0) { | 2306 | if (sz > 0) { |
| 2241 | if (copy_to_user(karg.replyFrameBufPtr, | 2307 | if (copy_to_user(karg.replyFrameBufPtr, |
| 2242 | &ioc->ioctl->ReplyFrame, sz)){ | 2308 | ioc->ioctl_cmds.reply, sz)){ |
| 2243 | printk(MYIOC_s_ERR_FMT | 2309 | printk(MYIOC_s_ERR_FMT |
| 2244 | "%s@%d::mptctl_do_mpt_command - " | 2310 | "%s@%d::mptctl_do_mpt_command - " |
| 2245 | "Unable to write out reply frame %p\n", | 2311 | "Unable to write out reply frame %p\n", |
| @@ -2252,10 +2318,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 2252 | 2318 | ||
| 2253 | /* If valid sense data, copy to user. | 2319 | /* If valid sense data, copy to user. |
| 2254 | */ | 2320 | */ |
| 2255 | if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) { | 2321 | if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_SENSE_VALID) { |
| 2256 | sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE); | 2322 | sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE); |
| 2257 | if (sz > 0) { | 2323 | if (sz > 0) { |
| 2258 | if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) { | 2324 | if (copy_to_user(karg.senseDataPtr, |
| 2325 | ioc->ioctl_cmds.sense, sz)) { | ||
| 2259 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " | 2326 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " |
| 2260 | "Unable to write sense data to user %p\n", | 2327 | "Unable to write sense data to user %p\n", |
| 2261 | ioc->name, __FILE__, __LINE__, | 2328 | ioc->name, __FILE__, __LINE__, |
| @@ -2269,7 +2336,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 2269 | /* If the overall status is _GOOD and data in, copy data | 2336 | /* If the overall status is _GOOD and data in, copy data |
| 2270 | * to user. | 2337 | * to user. |
| 2271 | */ | 2338 | */ |
| 2272 | if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) && | 2339 | if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD) && |
| 2273 | (karg.dataInSize > 0) && (bufIn.kptr)) { | 2340 | (karg.dataInSize > 0) && (bufIn.kptr)) { |
| 2274 | 2341 | ||
| 2275 | if (copy_to_user(karg.dataInBufPtr, | 2342 | if (copy_to_user(karg.dataInBufPtr, |
| @@ -2284,9 +2351,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 2284 | 2351 | ||
| 2285 | done_free_mem: | 2352 | done_free_mem: |
| 2286 | 2353 | ||
| 2287 | ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD | | 2354 | CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status) |
| 2288 | MPT_IOCTL_STATUS_SENSE_VALID | | 2355 | SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0); |
| 2289 | MPT_IOCTL_STATUS_RF_VALID ); | ||
| 2290 | 2356 | ||
| 2291 | /* Free the allocated memory. | 2357 | /* Free the allocated memory. |
| 2292 | */ | 2358 | */ |
| @@ -2336,6 +2402,8 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) | |||
| 2336 | ToolboxIstwiReadWriteRequest_t *IstwiRWRequest; | 2402 | ToolboxIstwiReadWriteRequest_t *IstwiRWRequest; |
| 2337 | MPT_FRAME_HDR *mf = NULL; | 2403 | MPT_FRAME_HDR *mf = NULL; |
| 2338 | MPIHeader_t *mpi_hdr; | 2404 | MPIHeader_t *mpi_hdr; |
| 2405 | unsigned long timeleft; | ||
| 2406 | int retval; | ||
| 2339 | 2407 | ||
| 2340 | /* Reset long to int. Should affect IA64 and SPARC only | 2408 | /* Reset long to int. Should affect IA64 and SPARC only |
| 2341 | */ | 2409 | */ |
| @@ -2466,9 +2534,9 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) | |||
| 2466 | MPT_SCSI_HOST *hd = shost_priv(ioc->sh); | 2534 | MPT_SCSI_HOST *hd = shost_priv(ioc->sh); |
| 2467 | 2535 | ||
| 2468 | if (hd && (cim_rev == 1)) { | 2536 | if (hd && (cim_rev == 1)) { |
| 2469 | karg.hard_resets = hd->hard_resets; | 2537 | karg.hard_resets = ioc->hard_resets; |
| 2470 | karg.soft_resets = hd->soft_resets; | 2538 | karg.soft_resets = ioc->soft_resets; |
| 2471 | karg.timeouts = hd->timeouts; | 2539 | karg.timeouts = ioc->timeouts; |
| 2472 | } | 2540 | } |
| 2473 | } | 2541 | } |
| 2474 | 2542 | ||
| @@ -2476,8 +2544,8 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) | |||
| 2476 | * Gather ISTWI(Industry Standard Two Wire Interface) Data | 2544 | * Gather ISTWI(Industry Standard Two Wire Interface) Data |
| 2477 | */ | 2545 | */ |
| 2478 | if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { | 2546 | if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { |
| 2479 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n", | 2547 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT |
| 2480 | ioc->name,__func__)); | 2548 | "%s, no msg frames!!\n", ioc->name, __func__)); |
| 2481 | goto out; | 2549 | goto out; |
| 2482 | } | 2550 | } |
| 2483 | 2551 | ||
| @@ -2498,22 +2566,29 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) | |||
| 2498 | pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma); | 2566 | pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma); |
| 2499 | if (!pbuf) | 2567 | if (!pbuf) |
| 2500 | goto out; | 2568 | goto out; |
| 2501 | mpt_add_sge((char *)&IstwiRWRequest->SGL, | 2569 | ioc->add_sge((char *)&IstwiRWRequest->SGL, |
| 2502 | (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma); | 2570 | (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma); |
| 2503 | 2571 | ||
| 2504 | ioc->ioctl->wait_done = 0; | 2572 | retval = 0; |
| 2573 | SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, | ||
| 2574 | IstwiRWRequest->MsgContext); | ||
| 2575 | INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status) | ||
| 2505 | mpt_put_msg_frame(mptctl_id, ioc, mf); | 2576 | mpt_put_msg_frame(mptctl_id, ioc, mf); |
| 2506 | 2577 | ||
| 2507 | rc = wait_event_timeout(mptctl_wait, | 2578 | retry_wait: |
| 2508 | ioc->ioctl->wait_done == 1, | 2579 | timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done, |
| 2509 | HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */); | 2580 | HZ*MPT_IOCTL_DEFAULT_TIMEOUT); |
| 2510 | 2581 | if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | |
| 2511 | if(rc <=0 && (ioc->ioctl->wait_done != 1 )) { | 2582 | retval = -ETIME; |
| 2512 | /* | 2583 | printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name, __func__); |
| 2513 | * Now we need to reset the board | 2584 | if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) { |
| 2514 | */ | 2585 | mpt_free_msg_frame(ioc, mf); |
| 2515 | mpt_free_msg_frame(ioc, mf); | 2586 | goto out; |
| 2516 | mptctl_timeout_expired(ioc->ioctl); | 2587 | } |
| 2588 | if (!timeleft) | ||
| 2589 | mptctl_timeout_expired(ioc, mf); | ||
| 2590 | else | ||
| 2591 | goto retry_wait; | ||
| 2517 | goto out; | 2592 | goto out; |
| 2518 | } | 2593 | } |
| 2519 | 2594 | ||
| @@ -2526,10 +2601,13 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) | |||
| 2526 | * bays have drives in them | 2601 | * bays have drives in them |
| 2527 | * pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3) | 2602 | * pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3) |
| 2528 | */ | 2603 | */ |
| 2529 | if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) | 2604 | if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) |
| 2530 | karg.rsvd = *(u32 *)pbuf; | 2605 | karg.rsvd = *(u32 *)pbuf; |
| 2531 | 2606 | ||
| 2532 | out: | 2607 | out: |
| 2608 | CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status) | ||
| 2609 | SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0); | ||
| 2610 | |||
| 2533 | if (pbuf) | 2611 | if (pbuf) |
| 2534 | pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma); | 2612 | pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma); |
| 2535 | 2613 | ||
| @@ -2753,7 +2831,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd, | |||
| 2753 | 2831 | ||
| 2754 | ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen); | 2832 | ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen); |
| 2755 | 2833 | ||
| 2756 | mutex_unlock(&iocp->ioctl->ioctl_mutex); | 2834 | mutex_unlock(&iocp->ioctl_cmds.mutex); |
| 2757 | 2835 | ||
| 2758 | return ret; | 2836 | return ret; |
| 2759 | } | 2837 | } |
| @@ -2807,7 +2885,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd, | |||
| 2807 | */ | 2885 | */ |
| 2808 | ret = mptctl_do_mpt_command (karg, &uarg->MF); | 2886 | ret = mptctl_do_mpt_command (karg, &uarg->MF); |
| 2809 | 2887 | ||
| 2810 | mutex_unlock(&iocp->ioctl->ioctl_mutex); | 2888 | mutex_unlock(&iocp->ioctl_cmds.mutex); |
| 2811 | 2889 | ||
| 2812 | return ret; | 2890 | return ret; |
| 2813 | } | 2891 | } |
| @@ -2859,21 +2937,10 @@ static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long a | |||
| 2859 | static int | 2937 | static int |
| 2860 | mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 2938 | mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 2861 | { | 2939 | { |
| 2862 | MPT_IOCTL *mem; | ||
| 2863 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | 2940 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); |
| 2864 | 2941 | ||
| 2865 | /* | 2942 | mutex_init(&ioc->ioctl_cmds.mutex); |
| 2866 | * Allocate and inite a MPT_IOCTL structure | 2943 | init_completion(&ioc->ioctl_cmds.done); |
| 2867 | */ | ||
| 2868 | mem = kzalloc(sizeof(MPT_IOCTL), GFP_KERNEL); | ||
| 2869 | if (!mem) { | ||
| 2870 | mptctl_remove(pdev); | ||
| 2871 | return -ENOMEM; | ||
| 2872 | } | ||
| 2873 | |||
| 2874 | ioc->ioctl = mem; | ||
| 2875 | ioc->ioctl->ioc = ioc; | ||
| 2876 | mutex_init(&ioc->ioctl->ioctl_mutex); | ||
| 2877 | return 0; | 2944 | return 0; |
| 2878 | } | 2945 | } |
| 2879 | 2946 | ||
| @@ -2887,9 +2954,6 @@ mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 2887 | static void | 2954 | static void |
| 2888 | mptctl_remove(struct pci_dev *pdev) | 2955 | mptctl_remove(struct pci_dev *pdev) |
| 2889 | { | 2956 | { |
| 2890 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | ||
| 2891 | |||
| 2892 | kfree ( ioc->ioctl ); | ||
| 2893 | } | 2957 | } |
| 2894 | 2958 | ||
| 2895 | static struct mpt_pci_driver mptctl_driver = { | 2959 | static struct mpt_pci_driver mptctl_driver = { |
| @@ -2929,6 +2993,7 @@ static int __init mptctl_init(void) | |||
| 2929 | goto out_fail; | 2993 | goto out_fail; |
| 2930 | } | 2994 | } |
| 2931 | 2995 | ||
| 2996 | mptctl_taskmgmt_id = mpt_register(mptctl_taskmgmt_reply, MPTCTL_DRIVER); | ||
| 2932 | mpt_reset_register(mptctl_id, mptctl_ioc_reset); | 2997 | mpt_reset_register(mptctl_id, mptctl_ioc_reset); |
| 2933 | mpt_event_register(mptctl_id, mptctl_event_process); | 2998 | mpt_event_register(mptctl_id, mptctl_event_process); |
| 2934 | 2999 | ||
| @@ -2953,6 +3018,7 @@ static void mptctl_exit(void) | |||
| 2953 | 3018 | ||
| 2954 | /* De-register callback handler from base module */ | 3019 | /* De-register callback handler from base module */ |
| 2955 | mpt_deregister(mptctl_id); | 3020 | mpt_deregister(mptctl_id); |
| 3021 | mpt_reset_deregister(mptctl_taskmgmt_id); | ||
| 2956 | 3022 | ||
| 2957 | mpt_device_driver_deregister(MPTCTL_DRIVER); | 3023 | mpt_device_driver_deregister(MPTCTL_DRIVER); |
| 2958 | 3024 | ||
diff --git a/drivers/message/fusion/mptdebug.h b/drivers/message/fusion/mptdebug.h index 510b9f492093..28e478879284 100644 --- a/drivers/message/fusion/mptdebug.h +++ b/drivers/message/fusion/mptdebug.h | |||
| @@ -58,6 +58,7 @@ | |||
| 58 | #define MPT_DEBUG_FC 0x00080000 | 58 | #define MPT_DEBUG_FC 0x00080000 |
| 59 | #define MPT_DEBUG_SAS 0x00100000 | 59 | #define MPT_DEBUG_SAS 0x00100000 |
| 60 | #define MPT_DEBUG_SAS_WIDE 0x00200000 | 60 | #define MPT_DEBUG_SAS_WIDE 0x00200000 |
| 61 | #define MPT_DEBUG_36GB_MEM 0x00400000 | ||
| 61 | 62 | ||
| 62 | /* | 63 | /* |
| 63 | * CONFIG_FUSION_LOGGING - enabled in Kconfig | 64 | * CONFIG_FUSION_LOGGING - enabled in Kconfig |
| @@ -135,6 +136,8 @@ | |||
| 135 | #define dsaswideprintk(IOC, CMD) \ | 136 | #define dsaswideprintk(IOC, CMD) \ |
| 136 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE) | 137 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE) |
| 137 | 138 | ||
| 139 | #define d36memprintk(IOC, CMD) \ | ||
| 140 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_36GB_MEM) | ||
| 138 | 141 | ||
| 139 | 142 | ||
| 140 | /* | 143 | /* |
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index c3c24fdf9fb6..e61df133a59e 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c | |||
| @@ -1251,17 +1251,15 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1251 | * A slightly different algorithm is required for | 1251 | * A slightly different algorithm is required for |
| 1252 | * 64bit SGEs. | 1252 | * 64bit SGEs. |
| 1253 | */ | 1253 | */ |
| 1254 | scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); | 1254 | scale = ioc->req_sz/ioc->SGE_size; |
| 1255 | if (sizeof(dma_addr_t) == sizeof(u64)) { | 1255 | if (ioc->sg_addr_size == sizeof(u64)) { |
| 1256 | numSGE = (scale - 1) * | 1256 | numSGE = (scale - 1) * |
| 1257 | (ioc->facts.MaxChainDepth-1) + scale + | 1257 | (ioc->facts.MaxChainDepth-1) + scale + |
| 1258 | (ioc->req_sz - 60) / (sizeof(dma_addr_t) + | 1258 | (ioc->req_sz - 60) / ioc->SGE_size; |
| 1259 | sizeof(u32)); | ||
| 1260 | } else { | 1259 | } else { |
| 1261 | numSGE = 1 + (scale - 1) * | 1260 | numSGE = 1 + (scale - 1) * |
| 1262 | (ioc->facts.MaxChainDepth-1) + scale + | 1261 | (ioc->facts.MaxChainDepth-1) + scale + |
| 1263 | (ioc->req_sz - 64) / (sizeof(dma_addr_t) + | 1262 | (ioc->req_sz - 64) / ioc->SGE_size; |
| 1264 | sizeof(u32)); | ||
| 1265 | } | 1263 | } |
| 1266 | 1264 | ||
| 1267 | if (numSGE < sh->sg_tablesize) { | 1265 | if (numSGE < sh->sg_tablesize) { |
| @@ -1292,9 +1290,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1292 | 1290 | ||
| 1293 | /* Clear the TM flags | 1291 | /* Clear the TM flags |
| 1294 | */ | 1292 | */ |
| 1295 | hd->tmPending = 0; | ||
| 1296 | hd->tmState = TM_STATE_NONE; | ||
| 1297 | hd->resetPending = 0; | ||
| 1298 | hd->abortSCpnt = NULL; | 1293 | hd->abortSCpnt = NULL; |
| 1299 | 1294 | ||
| 1300 | /* Clear the pointer used to store | 1295 | /* Clear the pointer used to store |
| @@ -1312,8 +1307,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1312 | hd->timer.data = (unsigned long) hd; | 1307 | hd->timer.data = (unsigned long) hd; |
| 1313 | hd->timer.function = mptscsih_timer_expired; | 1308 | hd->timer.function = mptscsih_timer_expired; |
| 1314 | 1309 | ||
| 1315 | init_waitqueue_head(&hd->scandv_waitq); | ||
| 1316 | hd->scandv_wait_done = 0; | ||
| 1317 | hd->last_queue_full = 0; | 1310 | hd->last_queue_full = 0; |
| 1318 | 1311 | ||
| 1319 | sh->transportt = mptfc_transport_template; | 1312 | sh->transportt = mptfc_transport_template; |
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 79f5433359f9..20e0b447e8e8 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
| @@ -93,8 +93,37 @@ static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS; | |||
| 93 | static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS; | 93 | static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS; |
| 94 | static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */ | 94 | static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */ |
| 95 | static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS; | 95 | static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS; |
| 96 | 96 | static u8 mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS; | |
| 97 | static void mptsas_hotplug_work(struct work_struct *work); | 97 | |
| 98 | static void mptsas_firmware_event_work(struct work_struct *work); | ||
| 99 | static void mptsas_send_sas_event(struct fw_event_work *fw_event); | ||
| 100 | static void mptsas_send_raid_event(struct fw_event_work *fw_event); | ||
| 101 | static void mptsas_send_ir2_event(struct fw_event_work *fw_event); | ||
| 102 | static void mptsas_parse_device_info(struct sas_identify *identify, | ||
| 103 | struct mptsas_devinfo *device_info); | ||
| 104 | static inline void mptsas_set_rphy(MPT_ADAPTER *ioc, | ||
| 105 | struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy); | ||
| 106 | static struct mptsas_phyinfo *mptsas_find_phyinfo_by_sas_address | ||
| 107 | (MPT_ADAPTER *ioc, u64 sas_address); | ||
| 108 | static int mptsas_sas_device_pg0(MPT_ADAPTER *ioc, | ||
| 109 | struct mptsas_devinfo *device_info, u32 form, u32 form_specific); | ||
| 110 | static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, | ||
| 111 | struct mptsas_enclosure *enclosure, u32 form, u32 form_specific); | ||
| 112 | static int mptsas_add_end_device(MPT_ADAPTER *ioc, | ||
| 113 | struct mptsas_phyinfo *phy_info); | ||
| 114 | static void mptsas_del_end_device(MPT_ADAPTER *ioc, | ||
| 115 | struct mptsas_phyinfo *phy_info); | ||
| 116 | static void mptsas_send_link_status_event(struct fw_event_work *fw_event); | ||
| 117 | static struct mptsas_portinfo *mptsas_find_portinfo_by_sas_address | ||
| 118 | (MPT_ADAPTER *ioc, u64 sas_address); | ||
| 119 | static void mptsas_expander_delete(MPT_ADAPTER *ioc, | ||
| 120 | struct mptsas_portinfo *port_info, u8 force); | ||
| 121 | static void mptsas_send_expander_event(struct fw_event_work *fw_event); | ||
| 122 | static void mptsas_not_responding_devices(MPT_ADAPTER *ioc); | ||
| 123 | static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc); | ||
| 124 | static void mptsas_broadcast_primative_work(struct fw_event_work *fw_event); | ||
| 125 | static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event); | ||
| 126 | static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id); | ||
| 98 | 127 | ||
| 99 | static void mptsas_print_phy_data(MPT_ADAPTER *ioc, | 128 | static void mptsas_print_phy_data(MPT_ADAPTER *ioc, |
| 100 | MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) | 129 | MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) |
| @@ -218,30 +247,125 @@ static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1) | |||
| 218 | le16_to_cpu(pg1->AttachedDevHandle))); | 247 | le16_to_cpu(pg1->AttachedDevHandle))); |
| 219 | } | 248 | } |
| 220 | 249 | ||
| 221 | static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) | 250 | /* inhibit sas firmware event handling */ |
| 251 | static void | ||
| 252 | mptsas_fw_event_off(MPT_ADAPTER *ioc) | ||
| 222 | { | 253 | { |
| 223 | struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); | 254 | unsigned long flags; |
| 224 | return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; | 255 | |
| 256 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 257 | ioc->fw_events_off = 1; | ||
| 258 | ioc->sas_discovery_quiesce_io = 0; | ||
| 259 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 260 | |||
| 225 | } | 261 | } |
| 226 | 262 | ||
| 227 | static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy) | 263 | /* enable sas firmware event handling */ |
| 264 | static void | ||
| 265 | mptsas_fw_event_on(MPT_ADAPTER *ioc) | ||
| 228 | { | 266 | { |
| 229 | struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); | 267 | unsigned long flags; |
| 230 | return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; | 268 | |
| 269 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 270 | ioc->fw_events_off = 0; | ||
| 271 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 231 | } | 272 | } |
| 232 | 273 | ||
| 233 | static struct mptsas_portinfo * | 274 | /* queue a sas firmware event */ |
| 234 | mptsas_get_hba_portinfo(MPT_ADAPTER *ioc) | 275 | static void |
| 276 | mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, | ||
| 277 | unsigned long delay) | ||
| 235 | { | 278 | { |
| 236 | struct list_head *head = &ioc->sas_topology; | 279 | unsigned long flags; |
| 237 | struct mptsas_portinfo *pi = NULL; | 280 | |
| 281 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 282 | list_add_tail(&fw_event->list, &ioc->fw_event_list); | ||
| 283 | INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work); | ||
| 284 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n", | ||
| 285 | ioc->name, __func__, fw_event)); | ||
| 286 | queue_delayed_work(ioc->fw_event_q, &fw_event->work, | ||
| 287 | delay); | ||
| 288 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 289 | } | ||
| 290 | |||
| 291 | /* requeue a sas firmware event */ | ||
| 292 | static void | ||
| 293 | mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, | ||
| 294 | unsigned long delay) | ||
| 295 | { | ||
| 296 | unsigned long flags; | ||
| 297 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 298 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task " | ||
| 299 | "(fw_event=0x%p)\n", ioc->name, __func__, fw_event)); | ||
| 300 | fw_event->retries++; | ||
| 301 | queue_delayed_work(ioc->fw_event_q, &fw_event->work, | ||
| 302 | msecs_to_jiffies(delay)); | ||
| 303 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 304 | } | ||
| 305 | |||
| 306 | /* free memory assoicated to a sas firmware event */ | ||
| 307 | static void | ||
| 308 | mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event) | ||
| 309 | { | ||
| 310 | unsigned long flags; | ||
| 311 | |||
| 312 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 313 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n", | ||
| 314 | ioc->name, __func__, fw_event)); | ||
| 315 | list_del(&fw_event->list); | ||
| 316 | kfree(fw_event); | ||
| 317 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 318 | } | ||
| 319 | |||
| 320 | /* walk the firmware event queue, and either stop or wait for | ||
| 321 | * outstanding events to complete */ | ||
| 322 | static void | ||
| 323 | mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc) | ||
| 324 | { | ||
| 325 | struct fw_event_work *fw_event, *next; | ||
| 326 | struct mptsas_target_reset_event *target_reset_list, *n; | ||
| 327 | u8 flush_q; | ||
| 328 | MPT_SCSI_HOST *hd = shost_priv(ioc->sh); | ||
| 329 | |||
| 330 | /* flush the target_reset_list */ | ||
| 331 | if (!list_empty(&hd->target_reset_list)) { | ||
| 332 | list_for_each_entry_safe(target_reset_list, n, | ||
| 333 | &hd->target_reset_list, list) { | ||
| 334 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 335 | "%s: removing target reset for id=%d\n", | ||
| 336 | ioc->name, __func__, | ||
| 337 | target_reset_list->sas_event_data.TargetID)); | ||
| 338 | list_del(&target_reset_list->list); | ||
| 339 | kfree(target_reset_list); | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | if (list_empty(&ioc->fw_event_list) || | ||
| 344 | !ioc->fw_event_q || in_interrupt()) | ||
| 345 | return; | ||
| 238 | 346 | ||
| 239 | /* always the first entry on sas_topology list */ | 347 | flush_q = 0; |
| 348 | list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) { | ||
| 349 | if (cancel_delayed_work(&fw_event->work)) | ||
| 350 | mptsas_free_fw_event(ioc, fw_event); | ||
| 351 | else | ||
| 352 | flush_q = 1; | ||
| 353 | } | ||
| 354 | if (flush_q) | ||
| 355 | flush_workqueue(ioc->fw_event_q); | ||
| 356 | } | ||
| 240 | 357 | ||
| 241 | if (!list_empty(head)) | ||
| 242 | pi = list_entry(head->next, struct mptsas_portinfo, list); | ||
| 243 | 358 | ||
| 244 | return pi; | 359 | static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) |
| 360 | { | ||
| 361 | struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); | ||
| 362 | return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; | ||
| 363 | } | ||
| 364 | |||
| 365 | static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy) | ||
| 366 | { | ||
| 367 | struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); | ||
| 368 | return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; | ||
| 245 | } | 369 | } |
| 246 | 370 | ||
| 247 | /* | 371 | /* |
| @@ -265,6 +389,38 @@ mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) | |||
| 265 | return rc; | 389 | return rc; |
| 266 | } | 390 | } |
| 267 | 391 | ||
| 392 | /** | ||
| 393 | * mptsas_find_portinfo_by_sas_address - | ||
| 394 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 395 | * @handle: | ||
| 396 | * | ||
| 397 | * This function should be called with the sas_topology_mutex already held | ||
| 398 | * | ||
| 399 | **/ | ||
| 400 | static struct mptsas_portinfo * | ||
| 401 | mptsas_find_portinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) | ||
| 402 | { | ||
| 403 | struct mptsas_portinfo *port_info, *rc = NULL; | ||
| 404 | int i; | ||
| 405 | |||
| 406 | if (sas_address >= ioc->hba_port_sas_addr && | ||
| 407 | sas_address < (ioc->hba_port_sas_addr + | ||
| 408 | ioc->hba_port_num_phy)) | ||
| 409 | return ioc->hba_port_info; | ||
| 410 | |||
| 411 | mutex_lock(&ioc->sas_topology_mutex); | ||
| 412 | list_for_each_entry(port_info, &ioc->sas_topology, list) | ||
| 413 | for (i = 0; i < port_info->num_phys; i++) | ||
| 414 | if (port_info->phy_info[i].identify.sas_address == | ||
| 415 | sas_address) { | ||
| 416 | rc = port_info; | ||
| 417 | goto out; | ||
| 418 | } | ||
| 419 | out: | ||
| 420 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 421 | return rc; | ||
| 422 | } | ||
| 423 | |||
| 268 | /* | 424 | /* |
| 269 | * Returns true if there is a scsi end device | 425 | * Returns true if there is a scsi end device |
| 270 | */ | 426 | */ |
| @@ -308,6 +464,7 @@ mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_detai | |||
| 308 | if(phy_info->port_details != port_details) | 464 | if(phy_info->port_details != port_details) |
| 309 | continue; | 465 | continue; |
| 310 | memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); | 466 | memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); |
| 467 | mptsas_set_rphy(ioc, phy_info, NULL); | ||
| 311 | phy_info->port_details = NULL; | 468 | phy_info->port_details = NULL; |
| 312 | } | 469 | } |
| 313 | kfree(port_details); | 470 | kfree(port_details); |
| @@ -379,6 +536,285 @@ starget) | |||
| 379 | phy_info->port_details->starget = starget; | 536 | phy_info->port_details->starget = starget; |
| 380 | } | 537 | } |
| 381 | 538 | ||
| 539 | /** | ||
| 540 | * mptsas_add_device_component - | ||
| 541 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 542 | * @channel: fw mapped id's | ||
| 543 | * @id: | ||
| 544 | * @sas_address: | ||
| 545 | * @device_info: | ||
| 546 | * | ||
| 547 | **/ | ||
| 548 | static void | ||
| 549 | mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id, | ||
| 550 | u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id) | ||
| 551 | { | ||
| 552 | struct mptsas_device_info *sas_info, *next; | ||
| 553 | struct scsi_device *sdev; | ||
| 554 | struct scsi_target *starget; | ||
| 555 | struct sas_rphy *rphy; | ||
| 556 | |||
| 557 | /* | ||
| 558 | * Delete all matching devices out of the list | ||
| 559 | */ | ||
| 560 | mutex_lock(&ioc->sas_device_info_mutex); | ||
| 561 | list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, | ||
| 562 | list) { | ||
| 563 | if (!sas_info->is_logical_volume && | ||
| 564 | (sas_info->sas_address == sas_address || | ||
| 565 | (sas_info->fw.channel == channel && | ||
| 566 | sas_info->fw.id == id))) { | ||
| 567 | list_del(&sas_info->list); | ||
| 568 | kfree(sas_info); | ||
| 569 | } | ||
| 570 | } | ||
| 571 | |||
| 572 | sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL); | ||
| 573 | if (!sas_info) | ||
| 574 | goto out; | ||
| 575 | |||
| 576 | /* | ||
| 577 | * Set Firmware mapping | ||
| 578 | */ | ||
| 579 | sas_info->fw.id = id; | ||
| 580 | sas_info->fw.channel = channel; | ||
| 581 | |||
| 582 | sas_info->sas_address = sas_address; | ||
| 583 | sas_info->device_info = device_info; | ||
| 584 | sas_info->slot = slot; | ||
| 585 | sas_info->enclosure_logical_id = enclosure_logical_id; | ||
| 586 | INIT_LIST_HEAD(&sas_info->list); | ||
| 587 | list_add_tail(&sas_info->list, &ioc->sas_device_info_list); | ||
| 588 | |||
| 589 | /* | ||
| 590 | * Set OS mapping | ||
| 591 | */ | ||
| 592 | shost_for_each_device(sdev, ioc->sh) { | ||
| 593 | starget = scsi_target(sdev); | ||
| 594 | rphy = dev_to_rphy(starget->dev.parent); | ||
| 595 | if (rphy->identify.sas_address == sas_address) { | ||
| 596 | sas_info->os.id = starget->id; | ||
| 597 | sas_info->os.channel = starget->channel; | ||
| 598 | } | ||
| 599 | } | ||
| 600 | |||
| 601 | out: | ||
| 602 | mutex_unlock(&ioc->sas_device_info_mutex); | ||
| 603 | return; | ||
| 604 | } | ||
| 605 | |||
| 606 | /** | ||
| 607 | * mptsas_add_device_component_by_fw - | ||
| 608 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 609 | * @channel: fw mapped id's | ||
| 610 | * @id: | ||
| 611 | * | ||
| 612 | **/ | ||
| 613 | static void | ||
| 614 | mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||
| 615 | { | ||
| 616 | struct mptsas_devinfo sas_device; | ||
| 617 | struct mptsas_enclosure enclosure_info; | ||
| 618 | int rc; | ||
| 619 | |||
| 620 | rc = mptsas_sas_device_pg0(ioc, &sas_device, | ||
| 621 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | ||
| 622 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||
| 623 | (channel << 8) + id); | ||
| 624 | if (rc) | ||
| 625 | return; | ||
| 626 | |||
| 627 | memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure)); | ||
| 628 | mptsas_sas_enclosure_pg0(ioc, &enclosure_info, | ||
| 629 | (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << | ||
| 630 | MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), | ||
| 631 | sas_device.handle_enclosure); | ||
| 632 | |||
| 633 | mptsas_add_device_component(ioc, sas_device.channel, | ||
| 634 | sas_device.id, sas_device.sas_address, sas_device.device_info, | ||
| 635 | sas_device.slot, enclosure_info.enclosure_logical_id); | ||
| 636 | } | ||
| 637 | |||
| 638 | /** | ||
| 639 | * mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding each individual device to list | ||
| 640 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 641 | * @channel: fw mapped id's | ||
| 642 | * @id: | ||
| 643 | * | ||
| 644 | **/ | ||
| 645 | static void | ||
| 646 | mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc, | ||
| 647 | struct scsi_target *starget) | ||
| 648 | { | ||
| 649 | CONFIGPARMS cfg; | ||
| 650 | ConfigPageHeader_t hdr; | ||
| 651 | dma_addr_t dma_handle; | ||
| 652 | pRaidVolumePage0_t buffer = NULL; | ||
| 653 | int i; | ||
| 654 | RaidPhysDiskPage0_t phys_disk; | ||
| 655 | struct mptsas_device_info *sas_info, *next; | ||
| 656 | |||
| 657 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
| 658 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
| 659 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; | ||
| 660 | /* assumption that all volumes on channel = 0 */ | ||
| 661 | cfg.pageAddr = starget->id; | ||
| 662 | cfg.cfghdr.hdr = &hdr; | ||
| 663 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 664 | cfg.timeout = 10; | ||
| 665 | |||
| 666 | if (mpt_config(ioc, &cfg) != 0) | ||
| 667 | goto out; | ||
| 668 | |||
| 669 | if (!hdr.PageLength) | ||
| 670 | goto out; | ||
| 671 | |||
| 672 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
| 673 | &dma_handle); | ||
| 674 | |||
| 675 | if (!buffer) | ||
| 676 | goto out; | ||
| 677 | |||
| 678 | cfg.physAddr = dma_handle; | ||
| 679 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 680 | |||
| 681 | if (mpt_config(ioc, &cfg) != 0) | ||
| 682 | goto out; | ||
| 683 | |||
| 684 | if (!buffer->NumPhysDisks) | ||
| 685 | goto out; | ||
| 686 | |||
| 687 | /* | ||
| 688 | * Adding entry for hidden components | ||
| 689 | */ | ||
| 690 | for (i = 0; i < buffer->NumPhysDisks; i++) { | ||
| 691 | |||
| 692 | if (mpt_raid_phys_disk_pg0(ioc, | ||
| 693 | buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) | ||
| 694 | continue; | ||
| 695 | |||
| 696 | mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus, | ||
| 697 | phys_disk.PhysDiskID); | ||
| 698 | |||
| 699 | mutex_lock(&ioc->sas_device_info_mutex); | ||
| 700 | list_for_each_entry(sas_info, &ioc->sas_device_info_list, | ||
| 701 | list) { | ||
| 702 | if (!sas_info->is_logical_volume && | ||
| 703 | (sas_info->fw.channel == phys_disk.PhysDiskBus && | ||
| 704 | sas_info->fw.id == phys_disk.PhysDiskID)) { | ||
| 705 | sas_info->is_hidden_raid_component = 1; | ||
| 706 | sas_info->volume_id = starget->id; | ||
| 707 | } | ||
| 708 | } | ||
| 709 | mutex_unlock(&ioc->sas_device_info_mutex); | ||
| 710 | |||
| 711 | } | ||
| 712 | |||
| 713 | /* | ||
| 714 | * Delete all matching devices out of the list | ||
| 715 | */ | ||
| 716 | mutex_lock(&ioc->sas_device_info_mutex); | ||
| 717 | list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, | ||
| 718 | list) { | ||
| 719 | if (sas_info->is_logical_volume && sas_info->fw.id == | ||
| 720 | starget->id) { | ||
| 721 | list_del(&sas_info->list); | ||
| 722 | kfree(sas_info); | ||
| 723 | } | ||
| 724 | } | ||
| 725 | |||
| 726 | sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL); | ||
| 727 | if (sas_info) { | ||
| 728 | sas_info->fw.id = starget->id; | ||
| 729 | sas_info->os.id = starget->id; | ||
| 730 | sas_info->os.channel = starget->channel; | ||
| 731 | sas_info->is_logical_volume = 1; | ||
| 732 | INIT_LIST_HEAD(&sas_info->list); | ||
| 733 | list_add_tail(&sas_info->list, &ioc->sas_device_info_list); | ||
| 734 | } | ||
| 735 | mutex_unlock(&ioc->sas_device_info_mutex); | ||
| 736 | |||
| 737 | out: | ||
| 738 | if (buffer) | ||
| 739 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
| 740 | dma_handle); | ||
| 741 | } | ||
| 742 | |||
| 743 | /** | ||
| 744 | * mptsas_add_device_component_starget - | ||
| 745 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 746 | * @starget: | ||
| 747 | * | ||
| 748 | **/ | ||
| 749 | static void | ||
| 750 | mptsas_add_device_component_starget(MPT_ADAPTER *ioc, | ||
| 751 | struct scsi_target *starget) | ||
| 752 | { | ||
| 753 | VirtTarget *vtarget; | ||
| 754 | struct sas_rphy *rphy; | ||
| 755 | struct mptsas_phyinfo *phy_info = NULL; | ||
| 756 | struct mptsas_enclosure enclosure_info; | ||
| 757 | |||
| 758 | rphy = dev_to_rphy(starget->dev.parent); | ||
| 759 | vtarget = starget->hostdata; | ||
| 760 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, | ||
| 761 | rphy->identify.sas_address); | ||
| 762 | if (!phy_info) | ||
| 763 | return; | ||
| 764 | |||
| 765 | memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure)); | ||
| 766 | mptsas_sas_enclosure_pg0(ioc, &enclosure_info, | ||
| 767 | (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << | ||
| 768 | MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), | ||
| 769 | phy_info->attached.handle_enclosure); | ||
| 770 | |||
| 771 | mptsas_add_device_component(ioc, phy_info->attached.channel, | ||
| 772 | phy_info->attached.id, phy_info->attached.sas_address, | ||
| 773 | phy_info->attached.device_info, | ||
| 774 | phy_info->attached.slot, enclosure_info.enclosure_logical_id); | ||
| 775 | } | ||
| 776 | |||
| 777 | /** | ||
| 778 | * mptsas_del_device_component_by_os - Once a device has been removed, we mark the entry in the list as being cached | ||
| 779 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 780 | * @channel: os mapped id's | ||
| 781 | * @id: | ||
| 782 | * | ||
| 783 | **/ | ||
| 784 | static void | ||
| 785 | mptsas_del_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||
| 786 | { | ||
| 787 | struct mptsas_device_info *sas_info, *next; | ||
| 788 | |||
| 789 | /* | ||
| 790 | * Set is_cached flag | ||
| 791 | */ | ||
| 792 | list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, | ||
| 793 | list) { | ||
| 794 | if (sas_info->os.channel == channel && sas_info->os.id == id) | ||
| 795 | sas_info->is_cached = 1; | ||
| 796 | } | ||
| 797 | } | ||
| 798 | |||
| 799 | /** | ||
| 800 | * mptsas_del_device_components - Cleaning the list | ||
| 801 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 802 | * | ||
| 803 | **/ | ||
| 804 | static void | ||
| 805 | mptsas_del_device_components(MPT_ADAPTER *ioc) | ||
| 806 | { | ||
| 807 | struct mptsas_device_info *sas_info, *next; | ||
| 808 | |||
| 809 | mutex_lock(&ioc->sas_device_info_mutex); | ||
| 810 | list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, | ||
| 811 | list) { | ||
| 812 | list_del(&sas_info->list); | ||
| 813 | kfree(sas_info); | ||
| 814 | } | ||
| 815 | mutex_unlock(&ioc->sas_device_info_mutex); | ||
| 816 | } | ||
| 817 | |||
| 382 | 818 | ||
| 383 | /* | 819 | /* |
| 384 | * mptsas_setup_wide_ports | 820 | * mptsas_setup_wide_ports |
| @@ -434,8 +870,8 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) | |||
| 434 | * Forming a port | 870 | * Forming a port |
| 435 | */ | 871 | */ |
| 436 | if (!port_details) { | 872 | if (!port_details) { |
| 437 | port_details = kzalloc(sizeof(*port_details), | 873 | port_details = kzalloc(sizeof(struct |
| 438 | GFP_KERNEL); | 874 | mptsas_portinfo_details), GFP_KERNEL); |
| 439 | if (!port_details) | 875 | if (!port_details) |
| 440 | goto out; | 876 | goto out; |
| 441 | port_details->num_phys = 1; | 877 | port_details->num_phys = 1; |
| @@ -523,15 +959,62 @@ mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 523 | VirtTarget *vtarget = NULL; | 959 | VirtTarget *vtarget = NULL; |
| 524 | 960 | ||
| 525 | shost_for_each_device(sdev, ioc->sh) { | 961 | shost_for_each_device(sdev, ioc->sh) { |
| 526 | if ((vdevice = sdev->hostdata) == NULL) | 962 | vdevice = sdev->hostdata; |
| 963 | if ((vdevice == NULL) || | ||
| 964 | (vdevice->vtarget == NULL)) | ||
| 965 | continue; | ||
| 966 | if ((vdevice->vtarget->tflags & | ||
| 967 | MPT_TARGET_FLAGS_RAID_COMPONENT || | ||
| 968 | vdevice->vtarget->raidVolume)) | ||
| 527 | continue; | 969 | continue; |
| 528 | if (vdevice->vtarget->id == id && | 970 | if (vdevice->vtarget->id == id && |
| 529 | vdevice->vtarget->channel == channel) | 971 | vdevice->vtarget->channel == channel) |
| 530 | vtarget = vdevice->vtarget; | 972 | vtarget = vdevice->vtarget; |
| 531 | } | 973 | } |
| 532 | return vtarget; | 974 | return vtarget; |
| 533 | } | 975 | } |
| 534 | 976 | ||
| 977 | static void | ||
| 978 | mptsas_queue_device_delete(MPT_ADAPTER *ioc, | ||
| 979 | MpiEventDataSasDeviceStatusChange_t *sas_event_data) | ||
| 980 | { | ||
| 981 | struct fw_event_work *fw_event; | ||
| 982 | int sz; | ||
| 983 | |||
| 984 | sz = offsetof(struct fw_event_work, event_data) + | ||
| 985 | sizeof(MpiEventDataSasDeviceStatusChange_t); | ||
| 986 | fw_event = kzalloc(sz, GFP_ATOMIC); | ||
| 987 | if (!fw_event) { | ||
| 988 | printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", | ||
| 989 | ioc->name, __func__, __LINE__); | ||
| 990 | return; | ||
| 991 | } | ||
| 992 | memcpy(fw_event->event_data, sas_event_data, | ||
| 993 | sizeof(MpiEventDataSasDeviceStatusChange_t)); | ||
| 994 | fw_event->event = MPI_EVENT_SAS_DEVICE_STATUS_CHANGE; | ||
| 995 | fw_event->ioc = ioc; | ||
| 996 | mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1)); | ||
| 997 | } | ||
| 998 | |||
| 999 | static void | ||
| 1000 | mptsas_queue_rescan(MPT_ADAPTER *ioc) | ||
| 1001 | { | ||
| 1002 | struct fw_event_work *fw_event; | ||
| 1003 | int sz; | ||
| 1004 | |||
| 1005 | sz = offsetof(struct fw_event_work, event_data); | ||
| 1006 | fw_event = kzalloc(sz, GFP_ATOMIC); | ||
| 1007 | if (!fw_event) { | ||
| 1008 | printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", | ||
| 1009 | ioc->name, __func__, __LINE__); | ||
| 1010 | return; | ||
| 1011 | } | ||
| 1012 | fw_event->event = -1; | ||
| 1013 | fw_event->ioc = ioc; | ||
| 1014 | mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1)); | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | |||
| 535 | /** | 1018 | /** |
| 536 | * mptsas_target_reset | 1019 | * mptsas_target_reset |
| 537 | * | 1020 | * |
| @@ -550,13 +1033,21 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 550 | { | 1033 | { |
| 551 | MPT_FRAME_HDR *mf; | 1034 | MPT_FRAME_HDR *mf; |
| 552 | SCSITaskMgmt_t *pScsiTm; | 1035 | SCSITaskMgmt_t *pScsiTm; |
| 553 | 1036 | if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) | |
| 554 | if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { | ||
| 555 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n", | ||
| 556 | ioc->name,__func__, __LINE__)); | ||
| 557 | return 0; | 1037 | return 0; |
| 1038 | |||
| 1039 | |||
| 1040 | mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc); | ||
| 1041 | if (mf == NULL) { | ||
| 1042 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT | ||
| 1043 | "%s, no msg frames @%d!!\n", ioc->name, | ||
| 1044 | __func__, __LINE__)); | ||
| 1045 | goto out_fail; | ||
| 558 | } | 1046 | } |
| 559 | 1047 | ||
| 1048 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n", | ||
| 1049 | ioc->name, mf)); | ||
| 1050 | |||
| 560 | /* Format the Request | 1051 | /* Format the Request |
| 561 | */ | 1052 | */ |
| 562 | pScsiTm = (SCSITaskMgmt_t *) mf; | 1053 | pScsiTm = (SCSITaskMgmt_t *) mf; |
| @@ -569,9 +1060,18 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 569 | 1060 | ||
| 570 | DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); | 1061 | DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); |
| 571 | 1062 | ||
| 572 | mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); | 1063 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 1064 | "TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n", | ||
| 1065 | ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id)); | ||
| 1066 | |||
| 1067 | mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf); | ||
| 573 | 1068 | ||
| 574 | return 1; | 1069 | return 1; |
| 1070 | |||
| 1071 | out_fail: | ||
| 1072 | |||
| 1073 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
| 1074 | return 0; | ||
| 575 | } | 1075 | } |
| 576 | 1076 | ||
| 577 | /** | 1077 | /** |
| @@ -602,11 +1102,12 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc, | |||
| 602 | 1102 | ||
| 603 | vtarget->deleted = 1; /* block IO */ | 1103 | vtarget->deleted = 1; /* block IO */ |
| 604 | 1104 | ||
| 605 | target_reset_list = kzalloc(sizeof(*target_reset_list), | 1105 | target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event), |
| 606 | GFP_ATOMIC); | 1106 | GFP_ATOMIC); |
| 607 | if (!target_reset_list) { | 1107 | if (!target_reset_list) { |
| 608 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", | 1108 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT |
| 609 | ioc->name,__func__, __LINE__)); | 1109 | "%s, failed to allocate mem @%d..!!\n", |
| 1110 | ioc->name, __func__, __LINE__)); | ||
| 610 | return; | 1111 | return; |
| 611 | } | 1112 | } |
| 612 | 1113 | ||
| @@ -614,84 +1115,101 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc, | |||
| 614 | sizeof(*sas_event_data)); | 1115 | sizeof(*sas_event_data)); |
| 615 | list_add_tail(&target_reset_list->list, &hd->target_reset_list); | 1116 | list_add_tail(&target_reset_list->list, &hd->target_reset_list); |
| 616 | 1117 | ||
| 617 | if (hd->resetPending) | 1118 | target_reset_list->time_count = jiffies; |
| 618 | return; | ||
| 619 | 1119 | ||
| 620 | if (mptsas_target_reset(ioc, channel, id)) { | 1120 | if (mptsas_target_reset(ioc, channel, id)) { |
| 621 | target_reset_list->target_reset_issued = 1; | 1121 | target_reset_list->target_reset_issued = 1; |
| 622 | hd->resetPending = 1; | ||
| 623 | } | 1122 | } |
| 624 | } | 1123 | } |
| 625 | 1124 | ||
| 626 | /** | 1125 | /** |
| 627 | * mptsas_dev_reset_complete | 1126 | * mptsas_taskmgmt_complete - complete SAS task management function |
| 628 | * | 1127 | * @ioc: Pointer to MPT_ADAPTER structure |
| 629 | * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, | ||
| 630 | * enable work queue to finish off removing device from upper layers. | ||
| 631 | * then send next TARGET_RESET in the queue. | ||
| 632 | * | ||
| 633 | * @ioc | ||
| 634 | * | 1128 | * |
| 1129 | * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, enable work | ||
| 1130 | * queue to finish off removing device from upper layers. then send next | ||
| 1131 | * TARGET_RESET in the queue. | ||
| 635 | **/ | 1132 | **/ |
| 636 | static void | 1133 | static int |
| 637 | mptsas_dev_reset_complete(MPT_ADAPTER *ioc) | 1134 | mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) |
| 638 | { | 1135 | { |
| 639 | MPT_SCSI_HOST *hd = shost_priv(ioc->sh); | 1136 | MPT_SCSI_HOST *hd = shost_priv(ioc->sh); |
| 640 | struct list_head *head = &hd->target_reset_list; | 1137 | struct list_head *head = &hd->target_reset_list; |
| 641 | struct mptsas_target_reset_event *target_reset_list; | ||
| 642 | struct mptsas_hotplug_event *ev; | ||
| 643 | EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data; | ||
| 644 | u8 id, channel; | 1138 | u8 id, channel; |
| 645 | __le64 sas_address; | 1139 | struct mptsas_target_reset_event *target_reset_list; |
| 1140 | SCSITaskMgmtReply_t *pScsiTmReply; | ||
| 1141 | |||
| 1142 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: " | ||
| 1143 | "(mf = %p, mr = %p)\n", ioc->name, mf, mr)); | ||
| 1144 | |||
| 1145 | pScsiTmReply = (SCSITaskMgmtReply_t *)mr; | ||
| 1146 | if (pScsiTmReply) { | ||
| 1147 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 1148 | "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n" | ||
| 1149 | "\ttask_type = 0x%02X, iocstatus = 0x%04X " | ||
| 1150 | "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, " | ||
| 1151 | "term_cmnds = %d\n", ioc->name, | ||
| 1152 | pScsiTmReply->Bus, pScsiTmReply->TargetID, | ||
| 1153 | pScsiTmReply->TaskType, | ||
| 1154 | le16_to_cpu(pScsiTmReply->IOCStatus), | ||
| 1155 | le32_to_cpu(pScsiTmReply->IOCLogInfo), | ||
| 1156 | pScsiTmReply->ResponseCode, | ||
| 1157 | le32_to_cpu(pScsiTmReply->TerminationCount))); | ||
| 1158 | |||
| 1159 | if (pScsiTmReply->ResponseCode) | ||
| 1160 | mptscsih_taskmgmt_response_code(ioc, | ||
| 1161 | pScsiTmReply->ResponseCode); | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | if (pScsiTmReply && (pScsiTmReply->TaskType == | ||
| 1165 | MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType == | ||
| 1166 | MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) { | ||
| 1167 | ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; | ||
| 1168 | ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID; | ||
| 1169 | memcpy(ioc->taskmgmt_cmds.reply, mr, | ||
| 1170 | min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength)); | ||
| 1171 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) { | ||
| 1172 | ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING; | ||
| 1173 | complete(&ioc->taskmgmt_cmds.done); | ||
| 1174 | return 1; | ||
| 1175 | } | ||
| 1176 | return 0; | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
| 646 | 1180 | ||
| 647 | if (list_empty(head)) | 1181 | if (list_empty(head)) |
| 648 | return; | 1182 | return 1; |
| 649 | 1183 | ||
| 650 | target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list); | 1184 | target_reset_list = list_entry(head->next, |
| 1185 | struct mptsas_target_reset_event, list); | ||
| 651 | 1186 | ||
| 652 | sas_event_data = &target_reset_list->sas_event_data; | 1187 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 653 | id = sas_event_data->TargetID; | 1188 | "TaskMgmt: completed (%d seconds)\n", |
| 654 | channel = sas_event_data->Bus; | 1189 | ioc->name, jiffies_to_msecs(jiffies - |
| 655 | hd->resetPending = 0; | 1190 | target_reset_list->time_count)/1000)); |
| 1191 | |||
| 1192 | id = pScsiTmReply->TargetID; | ||
| 1193 | channel = pScsiTmReply->Bus; | ||
| 1194 | target_reset_list->time_count = jiffies; | ||
| 656 | 1195 | ||
| 657 | /* | 1196 | /* |
| 658 | * retry target reset | 1197 | * retry target reset |
| 659 | */ | 1198 | */ |
| 660 | if (!target_reset_list->target_reset_issued) { | 1199 | if (!target_reset_list->target_reset_issued) { |
| 661 | if (mptsas_target_reset(ioc, channel, id)) { | 1200 | if (mptsas_target_reset(ioc, channel, id)) |
| 662 | target_reset_list->target_reset_issued = 1; | 1201 | target_reset_list->target_reset_issued = 1; |
| 663 | hd->resetPending = 1; | 1202 | return 1; |
| 664 | } | ||
| 665 | return; | ||
| 666 | } | 1203 | } |
| 667 | 1204 | ||
| 668 | /* | 1205 | /* |
| 669 | * enable work queue to remove device from upper layers | 1206 | * enable work queue to remove device from upper layers |
| 670 | */ | 1207 | */ |
| 671 | list_del(&target_reset_list->list); | 1208 | list_del(&target_reset_list->list); |
| 1209 | if ((mptsas_find_vtarget(ioc, channel, id)) && !ioc->fw_events_off) | ||
| 1210 | mptsas_queue_device_delete(ioc, | ||
| 1211 | &target_reset_list->sas_event_data); | ||
| 672 | 1212 | ||
| 673 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | ||
| 674 | if (!ev) { | ||
| 675 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", | ||
| 676 | ioc->name,__func__, __LINE__)); | ||
| 677 | return; | ||
| 678 | } | ||
| 679 | |||
| 680 | INIT_WORK(&ev->work, mptsas_hotplug_work); | ||
| 681 | ev->ioc = ioc; | ||
| 682 | ev->handle = le16_to_cpu(sas_event_data->DevHandle); | ||
| 683 | ev->parent_handle = | ||
| 684 | le16_to_cpu(sas_event_data->ParentDevHandle); | ||
| 685 | ev->channel = channel; | ||
| 686 | ev->id =id; | ||
| 687 | ev->phy_id = sas_event_data->PhyNum; | ||
| 688 | memcpy(&sas_address, &sas_event_data->SASAddress, | ||
| 689 | sizeof(__le64)); | ||
| 690 | ev->sas_address = le64_to_cpu(sas_address); | ||
| 691 | ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo); | ||
| 692 | ev->event_type = MPTSAS_DEL_DEVICE; | ||
| 693 | schedule_work(&ev->work); | ||
| 694 | kfree(target_reset_list); | ||
| 695 | 1213 | ||
| 696 | /* | 1214 | /* |
| 697 | * issue target reset to next device in the queue | 1215 | * issue target reset to next device in the queue |
| @@ -699,34 +1217,19 @@ mptsas_dev_reset_complete(MPT_ADAPTER *ioc) | |||
| 699 | 1217 | ||
| 700 | head = &hd->target_reset_list; | 1218 | head = &hd->target_reset_list; |
| 701 | if (list_empty(head)) | 1219 | if (list_empty(head)) |
| 702 | return; | 1220 | return 1; |
| 703 | 1221 | ||
| 704 | target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, | 1222 | target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, |
| 705 | list); | 1223 | list); |
| 706 | 1224 | ||
| 707 | sas_event_data = &target_reset_list->sas_event_data; | 1225 | id = target_reset_list->sas_event_data.TargetID; |
| 708 | id = sas_event_data->TargetID; | 1226 | channel = target_reset_list->sas_event_data.Bus; |
| 709 | channel = sas_event_data->Bus; | 1227 | target_reset_list->time_count = jiffies; |
| 710 | 1228 | ||
| 711 | if (mptsas_target_reset(ioc, channel, id)) { | 1229 | if (mptsas_target_reset(ioc, channel, id)) |
| 712 | target_reset_list->target_reset_issued = 1; | 1230 | target_reset_list->target_reset_issued = 1; |
| 713 | hd->resetPending = 1; | ||
| 714 | } | ||
| 715 | } | ||
| 716 | 1231 | ||
| 717 | /** | 1232 | return 1; |
| 718 | * mptsas_taskmgmt_complete | ||
| 719 | * | ||
| 720 | * @ioc | ||
| 721 | * @mf | ||
| 722 | * @mr | ||
| 723 | * | ||
| 724 | **/ | ||
| 725 | static int | ||
| 726 | mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | ||
| 727 | { | ||
| 728 | mptsas_dev_reset_complete(ioc); | ||
| 729 | return mptscsih_taskmgmt_complete(ioc, mf, mr); | ||
| 730 | } | 1233 | } |
| 731 | 1234 | ||
| 732 | /** | 1235 | /** |
| @@ -740,37 +1243,59 @@ static int | |||
| 740 | mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | 1243 | mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) |
| 741 | { | 1244 | { |
| 742 | MPT_SCSI_HOST *hd; | 1245 | MPT_SCSI_HOST *hd; |
| 743 | struct mptsas_target_reset_event *target_reset_list, *n; | ||
| 744 | int rc; | 1246 | int rc; |
| 745 | 1247 | ||
| 746 | rc = mptscsih_ioc_reset(ioc, reset_phase); | 1248 | rc = mptscsih_ioc_reset(ioc, reset_phase); |
| 1249 | if ((ioc->bus_type != SAS) || (!rc)) | ||
| 1250 | return rc; | ||
| 747 | 1251 | ||
| 748 | if (ioc->bus_type != SAS) | ||
| 749 | goto out; | ||
| 750 | |||
| 751 | if (reset_phase != MPT_IOC_POST_RESET) | ||
| 752 | goto out; | ||
| 753 | |||
| 754 | if (!ioc->sh || !ioc->sh->hostdata) | ||
| 755 | goto out; | ||
| 756 | hd = shost_priv(ioc->sh); | 1252 | hd = shost_priv(ioc->sh); |
| 757 | if (!hd->ioc) | 1253 | if (!hd->ioc) |
| 758 | goto out; | 1254 | goto out; |
| 759 | 1255 | ||
| 760 | if (list_empty(&hd->target_reset_list)) | 1256 | switch (reset_phase) { |
| 761 | goto out; | 1257 | case MPT_IOC_SETUP_RESET: |
| 762 | 1258 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | |
| 763 | /* flush the target_reset_list */ | 1259 | "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__)); |
| 764 | list_for_each_entry_safe(target_reset_list, n, | 1260 | mptsas_fw_event_off(ioc); |
| 765 | &hd->target_reset_list, list) { | 1261 | break; |
| 766 | list_del(&target_reset_list->list); | 1262 | case MPT_IOC_PRE_RESET: |
| 767 | kfree(target_reset_list); | 1263 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 1264 | "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__)); | ||
| 1265 | break; | ||
| 1266 | case MPT_IOC_POST_RESET: | ||
| 1267 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 1268 | "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__)); | ||
| 1269 | if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) { | ||
| 1270 | ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET; | ||
| 1271 | complete(&ioc->sas_mgmt.done); | ||
| 1272 | } | ||
| 1273 | mptsas_cleanup_fw_event_q(ioc); | ||
| 1274 | mptsas_queue_rescan(ioc); | ||
| 1275 | mptsas_fw_event_on(ioc); | ||
| 1276 | break; | ||
| 1277 | default: | ||
| 1278 | break; | ||
| 768 | } | 1279 | } |
| 769 | 1280 | ||
| 770 | out: | 1281 | out: |
| 771 | return rc; | 1282 | return rc; |
| 772 | } | 1283 | } |
| 773 | 1284 | ||
| 1285 | |||
| 1286 | /** | ||
| 1287 | * enum device_state - | ||
| 1288 | * @DEVICE_RETRY: need to retry the TUR | ||
| 1289 | * @DEVICE_ERROR: TUR return error, don't add device | ||
| 1290 | * @DEVICE_READY: device can be added | ||
| 1291 | * | ||
| 1292 | */ | ||
| 1293 | enum device_state{ | ||
| 1294 | DEVICE_RETRY, | ||
| 1295 | DEVICE_ERROR, | ||
| 1296 | DEVICE_READY, | ||
| 1297 | }; | ||
| 1298 | |||
| 774 | static int | 1299 | static int |
| 775 | mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, | 1300 | mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, |
| 776 | u32 form, u32 form_specific) | 1301 | u32 form, u32 form_specific) |
| @@ -836,15 +1361,308 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, | |||
| 836 | return error; | 1361 | return error; |
| 837 | } | 1362 | } |
| 838 | 1363 | ||
| 1364 | /** | ||
| 1365 | * mptsas_add_end_device - report a new end device to sas transport layer | ||
| 1366 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 1367 | * @phy_info: decribes attached device | ||
| 1368 | * | ||
| 1369 | * return (0) success (1) failure | ||
| 1370 | * | ||
| 1371 | **/ | ||
| 1372 | static int | ||
| 1373 | mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info) | ||
| 1374 | { | ||
| 1375 | struct sas_rphy *rphy; | ||
| 1376 | struct sas_port *port; | ||
| 1377 | struct sas_identify identify; | ||
| 1378 | char *ds = NULL; | ||
| 1379 | u8 fw_id; | ||
| 1380 | |||
| 1381 | if (!phy_info) { | ||
| 1382 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 1383 | "%s: exit at line=%d\n", ioc->name, | ||
| 1384 | __func__, __LINE__)); | ||
| 1385 | return 1; | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | fw_id = phy_info->attached.id; | ||
| 1389 | |||
| 1390 | if (mptsas_get_rphy(phy_info)) { | ||
| 1391 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 1392 | "%s: fw_id=%d exit at line=%d\n", ioc->name, | ||
| 1393 | __func__, fw_id, __LINE__)); | ||
| 1394 | return 2; | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | port = mptsas_get_port(phy_info); | ||
| 1398 | if (!port) { | ||
| 1399 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 1400 | "%s: fw_id=%d exit at line=%d\n", ioc->name, | ||
| 1401 | __func__, fw_id, __LINE__)); | ||
| 1402 | return 3; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | if (phy_info->attached.device_info & | ||
| 1406 | MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||
| 1407 | ds = "ssp"; | ||
| 1408 | if (phy_info->attached.device_info & | ||
| 1409 | MPI_SAS_DEVICE_INFO_STP_TARGET) | ||
| 1410 | ds = "stp"; | ||
| 1411 | if (phy_info->attached.device_info & | ||
| 1412 | MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||
| 1413 | ds = "sata"; | ||
| 1414 | |||
| 1415 | printk(MYIOC_s_INFO_FMT "attaching %s device: fw_channel %d, fw_id %d," | ||
| 1416 | " phy %d, sas_addr 0x%llx\n", ioc->name, ds, | ||
| 1417 | phy_info->attached.channel, phy_info->attached.id, | ||
| 1418 | phy_info->attached.phy_id, (unsigned long long) | ||
| 1419 | phy_info->attached.sas_address); | ||
| 1420 | |||
| 1421 | mptsas_parse_device_info(&identify, &phy_info->attached); | ||
| 1422 | rphy = sas_end_device_alloc(port); | ||
| 1423 | if (!rphy) { | ||
| 1424 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 1425 | "%s: fw_id=%d exit at line=%d\n", ioc->name, | ||
| 1426 | __func__, fw_id, __LINE__)); | ||
| 1427 | return 5; /* non-fatal: an rphy can be added later */ | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | rphy->identify = identify; | ||
| 1431 | if (sas_rphy_add(rphy)) { | ||
| 1432 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 1433 | "%s: fw_id=%d exit at line=%d\n", ioc->name, | ||
| 1434 | __func__, fw_id, __LINE__)); | ||
| 1435 | sas_rphy_free(rphy); | ||
| 1436 | return 6; | ||
| 1437 | } | ||
| 1438 | mptsas_set_rphy(ioc, phy_info, rphy); | ||
| 1439 | return 0; | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | /** | ||
| 1443 | * mptsas_del_end_device - report a deleted end device to sas transport layer | ||
| 1444 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 1445 | * @phy_info: decribes attached device | ||
| 1446 | * | ||
| 1447 | **/ | ||
| 1448 | static void | ||
| 1449 | mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info) | ||
| 1450 | { | ||
| 1451 | struct sas_rphy *rphy; | ||
| 1452 | struct sas_port *port; | ||
| 1453 | struct mptsas_portinfo *port_info; | ||
| 1454 | struct mptsas_phyinfo *phy_info_parent; | ||
| 1455 | int i; | ||
| 1456 | char *ds = NULL; | ||
| 1457 | u8 fw_id; | ||
| 1458 | u64 sas_address; | ||
| 1459 | |||
| 1460 | if (!phy_info) | ||
| 1461 | return; | ||
| 1462 | |||
| 1463 | fw_id = phy_info->attached.id; | ||
| 1464 | sas_address = phy_info->attached.sas_address; | ||
| 1465 | |||
| 1466 | if (!phy_info->port_details) { | ||
| 1467 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 1468 | "%s: fw_id=%d exit at line=%d\n", ioc->name, | ||
| 1469 | __func__, fw_id, __LINE__)); | ||
| 1470 | return; | ||
| 1471 | } | ||
| 1472 | rphy = mptsas_get_rphy(phy_info); | ||
| 1473 | if (!rphy) { | ||
| 1474 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 1475 | "%s: fw_id=%d exit at line=%d\n", ioc->name, | ||
| 1476 | __func__, fw_id, __LINE__)); | ||
| 1477 | return; | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR | ||
| 1481 | || phy_info->attached.device_info | ||
| 1482 | & MPI_SAS_DEVICE_INFO_SMP_INITIATOR | ||
| 1483 | || phy_info->attached.device_info | ||
| 1484 | & MPI_SAS_DEVICE_INFO_STP_INITIATOR) | ||
| 1485 | ds = "initiator"; | ||
| 1486 | if (phy_info->attached.device_info & | ||
| 1487 | MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||
| 1488 | ds = "ssp"; | ||
| 1489 | if (phy_info->attached.device_info & | ||
| 1490 | MPI_SAS_DEVICE_INFO_STP_TARGET) | ||
| 1491 | ds = "stp"; | ||
| 1492 | if (phy_info->attached.device_info & | ||
| 1493 | MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||
| 1494 | ds = "sata"; | ||
| 1495 | |||
| 1496 | dev_printk(KERN_DEBUG, &rphy->dev, MYIOC_s_FMT | ||
| 1497 | "removing %s device: fw_channel %d, fw_id %d, phy %d," | ||
| 1498 | "sas_addr 0x%llx\n", ioc->name, ds, phy_info->attached.channel, | ||
| 1499 | phy_info->attached.id, phy_info->attached.phy_id, | ||
| 1500 | (unsigned long long) sas_address); | ||
| 1501 | |||
| 1502 | port = mptsas_get_port(phy_info); | ||
| 1503 | if (!port) { | ||
| 1504 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 1505 | "%s: fw_id=%d exit at line=%d\n", ioc->name, | ||
| 1506 | __func__, fw_id, __LINE__)); | ||
| 1507 | return; | ||
| 1508 | } | ||
| 1509 | port_info = phy_info->portinfo; | ||
| 1510 | phy_info_parent = port_info->phy_info; | ||
| 1511 | for (i = 0; i < port_info->num_phys; i++, phy_info_parent++) { | ||
| 1512 | if (!phy_info_parent->phy) | ||
| 1513 | continue; | ||
| 1514 | if (phy_info_parent->attached.sas_address != | ||
| 1515 | sas_address) | ||
| 1516 | continue; | ||
| 1517 | dev_printk(KERN_DEBUG, &phy_info_parent->phy->dev, | ||
| 1518 | MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", | ||
| 1519 | ioc->name, phy_info_parent->phy_id, | ||
| 1520 | phy_info_parent->phy); | ||
| 1521 | sas_port_delete_phy(port, phy_info_parent->phy); | ||
| 1522 | } | ||
| 1523 | |||
| 1524 | dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT | ||
| 1525 | "delete port %d, sas_addr (0x%llx)\n", ioc->name, | ||
| 1526 | port->port_identifier, (unsigned long long)sas_address); | ||
| 1527 | sas_port_delete(port); | ||
| 1528 | mptsas_set_port(ioc, phy_info, NULL); | ||
| 1529 | mptsas_port_delete(ioc, phy_info->port_details); | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | struct mptsas_phyinfo * | ||
| 1533 | mptsas_refreshing_device_handles(MPT_ADAPTER *ioc, | ||
| 1534 | struct mptsas_devinfo *sas_device) | ||
| 1535 | { | ||
| 1536 | struct mptsas_phyinfo *phy_info; | ||
| 1537 | struct mptsas_portinfo *port_info; | ||
| 1538 | int i; | ||
| 1539 | |||
| 1540 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, | ||
| 1541 | sas_device->sas_address); | ||
| 1542 | if (!phy_info) | ||
| 1543 | goto out; | ||
| 1544 | port_info = phy_info->portinfo; | ||
| 1545 | if (!port_info) | ||
| 1546 | goto out; | ||
| 1547 | mutex_lock(&ioc->sas_topology_mutex); | ||
| 1548 | for (i = 0; i < port_info->num_phys; i++) { | ||
| 1549 | if (port_info->phy_info[i].attached.sas_address != | ||
| 1550 | sas_device->sas_address) | ||
| 1551 | continue; | ||
| 1552 | port_info->phy_info[i].attached.channel = sas_device->channel; | ||
| 1553 | port_info->phy_info[i].attached.id = sas_device->id; | ||
| 1554 | port_info->phy_info[i].attached.sas_address = | ||
| 1555 | sas_device->sas_address; | ||
| 1556 | port_info->phy_info[i].attached.handle = sas_device->handle; | ||
| 1557 | port_info->phy_info[i].attached.handle_parent = | ||
| 1558 | sas_device->handle_parent; | ||
| 1559 | port_info->phy_info[i].attached.handle_enclosure = | ||
| 1560 | sas_device->handle_enclosure; | ||
| 1561 | } | ||
| 1562 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 1563 | out: | ||
| 1564 | return phy_info; | ||
| 1565 | } | ||
| 1566 | |||
| 1567 | /** | ||
| 1568 | * mptsas_firmware_event_work - work thread for processing fw events | ||
| 1569 | * @work: work queue payload containing info describing the event | ||
| 1570 | * Context: user | ||
| 1571 | * | ||
| 1572 | */ | ||
| 1573 | static void | ||
| 1574 | mptsas_firmware_event_work(struct work_struct *work) | ||
| 1575 | { | ||
| 1576 | struct fw_event_work *fw_event = | ||
| 1577 | container_of(work, struct fw_event_work, work.work); | ||
| 1578 | MPT_ADAPTER *ioc = fw_event->ioc; | ||
| 1579 | |||
| 1580 | /* special rescan topology handling */ | ||
| 1581 | if (fw_event->event == -1) { | ||
| 1582 | if (ioc->in_rescan) { | ||
| 1583 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 1584 | "%s: rescan ignored as it is in progress\n", | ||
| 1585 | ioc->name, __func__)); | ||
| 1586 | return; | ||
| 1587 | } | ||
| 1588 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: rescan after " | ||
| 1589 | "reset\n", ioc->name, __func__)); | ||
| 1590 | ioc->in_rescan = 1; | ||
| 1591 | mptsas_not_responding_devices(ioc); | ||
| 1592 | mptsas_scan_sas_topology(ioc); | ||
| 1593 | ioc->in_rescan = 0; | ||
| 1594 | mptsas_free_fw_event(ioc, fw_event); | ||
| 1595 | return; | ||
| 1596 | } | ||
| 1597 | |||
| 1598 | /* events handling turned off during host reset */ | ||
| 1599 | if (ioc->fw_events_off) { | ||
| 1600 | mptsas_free_fw_event(ioc, fw_event); | ||
| 1601 | return; | ||
| 1602 | } | ||
| 1603 | |||
| 1604 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_event=(0x%p), " | ||
| 1605 | "event = (0x%02x)\n", ioc->name, __func__, fw_event, | ||
| 1606 | (fw_event->event & 0xFF))); | ||
| 1607 | |||
| 1608 | switch (fw_event->event) { | ||
| 1609 | case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: | ||
| 1610 | mptsas_send_sas_event(fw_event); | ||
| 1611 | break; | ||
| 1612 | case MPI_EVENT_INTEGRATED_RAID: | ||
| 1613 | mptsas_send_raid_event(fw_event); | ||
| 1614 | break; | ||
| 1615 | case MPI_EVENT_IR2: | ||
| 1616 | mptsas_send_ir2_event(fw_event); | ||
| 1617 | break; | ||
| 1618 | case MPI_EVENT_PERSISTENT_TABLE_FULL: | ||
| 1619 | mptbase_sas_persist_operation(ioc, | ||
| 1620 | MPI_SAS_OP_CLEAR_NOT_PRESENT); | ||
| 1621 | mptsas_free_fw_event(ioc, fw_event); | ||
| 1622 | break; | ||
| 1623 | case MPI_EVENT_SAS_BROADCAST_PRIMITIVE: | ||
| 1624 | mptsas_broadcast_primative_work(fw_event); | ||
| 1625 | break; | ||
| 1626 | case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE: | ||
| 1627 | mptsas_send_expander_event(fw_event); | ||
| 1628 | break; | ||
| 1629 | case MPI_EVENT_SAS_PHY_LINK_STATUS: | ||
| 1630 | mptsas_send_link_status_event(fw_event); | ||
| 1631 | break; | ||
| 1632 | case MPI_EVENT_QUEUE_FULL: | ||
| 1633 | mptsas_handle_queue_full_event(fw_event); | ||
| 1634 | break; | ||
| 1635 | } | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | |||
| 1639 | |||
| 839 | static int | 1640 | static int |
| 840 | mptsas_slave_configure(struct scsi_device *sdev) | 1641 | mptsas_slave_configure(struct scsi_device *sdev) |
| 841 | { | 1642 | { |
| 1643 | struct Scsi_Host *host = sdev->host; | ||
| 1644 | MPT_SCSI_HOST *hd = shost_priv(host); | ||
| 1645 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 1646 | VirtDevice *vdevice = sdev->hostdata; | ||
| 842 | 1647 | ||
| 843 | if (sdev->channel == MPTSAS_RAID_CHANNEL) | 1648 | if (vdevice->vtarget->deleted) { |
| 1649 | sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n"); | ||
| 1650 | vdevice->vtarget->deleted = 0; | ||
| 1651 | } | ||
| 1652 | |||
| 1653 | /* | ||
| 1654 | * RAID volumes placed beyond the last expected port. | ||
| 1655 | * Ignore sending sas mode pages in that case.. | ||
| 1656 | */ | ||
| 1657 | if (sdev->channel == MPTSAS_RAID_CHANNEL) { | ||
| 1658 | mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev)); | ||
| 844 | goto out; | 1659 | goto out; |
| 1660 | } | ||
| 845 | 1661 | ||
| 846 | sas_read_port_mode_page(sdev); | 1662 | sas_read_port_mode_page(sdev); |
| 847 | 1663 | ||
| 1664 | mptsas_add_device_component_starget(ioc, scsi_target(sdev)); | ||
| 1665 | |||
| 848 | out: | 1666 | out: |
| 849 | return mptscsih_slave_configure(sdev); | 1667 | return mptscsih_slave_configure(sdev); |
| 850 | } | 1668 | } |
| @@ -875,9 +1693,18 @@ mptsas_target_alloc(struct scsi_target *starget) | |||
| 875 | * RAID volumes placed beyond the last expected port. | 1693 | * RAID volumes placed beyond the last expected port. |
| 876 | */ | 1694 | */ |
| 877 | if (starget->channel == MPTSAS_RAID_CHANNEL) { | 1695 | if (starget->channel == MPTSAS_RAID_CHANNEL) { |
| 878 | for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) | 1696 | if (!ioc->raid_data.pIocPg2) { |
| 879 | if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) | 1697 | kfree(vtarget); |
| 880 | channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; | 1698 | return -ENXIO; |
| 1699 | } | ||
| 1700 | for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { | ||
| 1701 | if (id == ioc->raid_data.pIocPg2-> | ||
| 1702 | RaidVolume[i].VolumeID) { | ||
| 1703 | channel = ioc->raid_data.pIocPg2-> | ||
| 1704 | RaidVolume[i].VolumeBus; | ||
| 1705 | } | ||
| 1706 | } | ||
| 1707 | vtarget->raidVolume = 1; | ||
| 881 | goto out; | 1708 | goto out; |
| 882 | } | 1709 | } |
| 883 | 1710 | ||
| @@ -926,11 +1753,18 @@ mptsas_target_destroy(struct scsi_target *starget) | |||
| 926 | struct sas_rphy *rphy; | 1753 | struct sas_rphy *rphy; |
| 927 | struct mptsas_portinfo *p; | 1754 | struct mptsas_portinfo *p; |
| 928 | int i; | 1755 | int i; |
| 929 | MPT_ADAPTER *ioc = hd->ioc; | 1756 | MPT_ADAPTER *ioc = hd->ioc; |
| 1757 | VirtTarget *vtarget; | ||
| 930 | 1758 | ||
| 931 | if (!starget->hostdata) | 1759 | if (!starget->hostdata) |
| 932 | return; | 1760 | return; |
| 933 | 1761 | ||
| 1762 | vtarget = starget->hostdata; | ||
| 1763 | |||
| 1764 | mptsas_del_device_component_by_os(ioc, starget->channel, | ||
| 1765 | starget->id); | ||
| 1766 | |||
| 1767 | |||
| 934 | if (starget->channel == MPTSAS_RAID_CHANNEL) | 1768 | if (starget->channel == MPTSAS_RAID_CHANNEL) |
| 935 | goto out; | 1769 | goto out; |
| 936 | 1770 | ||
| @@ -940,12 +1774,21 @@ mptsas_target_destroy(struct scsi_target *starget) | |||
| 940 | if (p->phy_info[i].attached.sas_address != | 1774 | if (p->phy_info[i].attached.sas_address != |
| 941 | rphy->identify.sas_address) | 1775 | rphy->identify.sas_address) |
| 942 | continue; | 1776 | continue; |
| 1777 | |||
| 1778 | starget_printk(KERN_INFO, starget, MYIOC_s_FMT | ||
| 1779 | "delete device: fw_channel %d, fw_id %d, phy %d, " | ||
| 1780 | "sas_addr 0x%llx\n", ioc->name, | ||
| 1781 | p->phy_info[i].attached.channel, | ||
| 1782 | p->phy_info[i].attached.id, | ||
| 1783 | p->phy_info[i].attached.phy_id, (unsigned long long) | ||
| 1784 | p->phy_info[i].attached.sas_address); | ||
| 1785 | |||
| 943 | mptsas_set_starget(&p->phy_info[i], NULL); | 1786 | mptsas_set_starget(&p->phy_info[i], NULL); |
| 944 | goto out; | ||
| 945 | } | 1787 | } |
| 946 | } | 1788 | } |
| 947 | 1789 | ||
| 948 | out: | 1790 | out: |
| 1791 | vtarget->starget = NULL; | ||
| 949 | kfree(starget->hostdata); | 1792 | kfree(starget->hostdata); |
| 950 | starget->hostdata = NULL; | 1793 | starget->hostdata = NULL; |
| 951 | } | 1794 | } |
| @@ -1008,6 +1851,8 @@ mptsas_slave_alloc(struct scsi_device *sdev) | |||
| 1008 | static int | 1851 | static int |
| 1009 | mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | 1852 | mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) |
| 1010 | { | 1853 | { |
| 1854 | MPT_SCSI_HOST *hd; | ||
| 1855 | MPT_ADAPTER *ioc; | ||
| 1011 | VirtDevice *vdevice = SCpnt->device->hostdata; | 1856 | VirtDevice *vdevice = SCpnt->device->hostdata; |
| 1012 | 1857 | ||
| 1013 | if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) { | 1858 | if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) { |
| @@ -1016,6 +1861,12 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
| 1016 | return 0; | 1861 | return 0; |
| 1017 | } | 1862 | } |
| 1018 | 1863 | ||
| 1864 | hd = shost_priv(SCpnt->device->host); | ||
| 1865 | ioc = hd->ioc; | ||
| 1866 | |||
| 1867 | if (ioc->sas_discovery_quiesce_io) | ||
| 1868 | return SCSI_MLQUEUE_HOST_BUSY; | ||
| 1869 | |||
| 1019 | // scsi_print_command(SCpnt); | 1870 | // scsi_print_command(SCpnt); |
| 1020 | 1871 | ||
| 1021 | return mptscsih_qcmd(SCpnt,done); | 1872 | return mptscsih_qcmd(SCpnt,done); |
| @@ -1114,14 +1965,19 @@ static int mptsas_get_linkerrors(struct sas_phy *phy) | |||
| 1114 | static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, | 1965 | static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, |
| 1115 | MPT_FRAME_HDR *reply) | 1966 | MPT_FRAME_HDR *reply) |
| 1116 | { | 1967 | { |
| 1117 | ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD; | 1968 | ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD; |
| 1118 | if (reply != NULL) { | 1969 | if (reply != NULL) { |
| 1119 | ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID; | 1970 | ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID; |
| 1120 | memcpy(ioc->sas_mgmt.reply, reply, | 1971 | memcpy(ioc->sas_mgmt.reply, reply, |
| 1121 | min(ioc->reply_sz, 4 * reply->u.reply.MsgLength)); | 1972 | min(ioc->reply_sz, 4 * reply->u.reply.MsgLength)); |
| 1122 | } | 1973 | } |
| 1123 | complete(&ioc->sas_mgmt.done); | 1974 | |
| 1124 | return 1; | 1975 | if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) { |
| 1976 | ioc->sas_mgmt.status &= ~MPT_MGMT_STATUS_PENDING; | ||
| 1977 | complete(&ioc->sas_mgmt.done); | ||
| 1978 | return 1; | ||
| 1979 | } | ||
| 1980 | return 0; | ||
| 1125 | } | 1981 | } |
| 1126 | 1982 | ||
| 1127 | static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) | 1983 | static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) |
| @@ -1160,6 +2016,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) | |||
| 1160 | MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET; | 2016 | MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET; |
| 1161 | req->PhyNum = phy->identify.phy_identifier; | 2017 | req->PhyNum = phy->identify.phy_identifier; |
| 1162 | 2018 | ||
| 2019 | INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status) | ||
| 1163 | mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf); | 2020 | mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf); |
| 1164 | 2021 | ||
| 1165 | timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, | 2022 | timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, |
| @@ -1174,7 +2031,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) | |||
| 1174 | 2031 | ||
| 1175 | /* a reply frame is expected */ | 2032 | /* a reply frame is expected */ |
| 1176 | if ((ioc->sas_mgmt.status & | 2033 | if ((ioc->sas_mgmt.status & |
| 1177 | MPT_IOCTL_STATUS_RF_VALID) == 0) { | 2034 | MPT_MGMT_STATUS_RF_VALID) == 0) { |
| 1178 | error = -ENXIO; | 2035 | error = -ENXIO; |
| 1179 | goto out_unlock; | 2036 | goto out_unlock; |
| 1180 | } | 2037 | } |
| @@ -1191,6 +2048,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) | |||
| 1191 | error = 0; | 2048 | error = 0; |
| 1192 | 2049 | ||
| 1193 | out_unlock: | 2050 | out_unlock: |
| 2051 | CLEAR_MGMT_STATUS(ioc->sas_mgmt.status) | ||
| 1194 | mutex_unlock(&ioc->sas_mgmt.mutex); | 2052 | mutex_unlock(&ioc->sas_mgmt.mutex); |
| 1195 | out: | 2053 | out: |
| 1196 | return error; | 2054 | return error; |
| @@ -1304,7 +2162,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1304 | struct mptsas_portinfo *port_info; | 2162 | struct mptsas_portinfo *port_info; |
| 1305 | 2163 | ||
| 1306 | mutex_lock(&ioc->sas_topology_mutex); | 2164 | mutex_lock(&ioc->sas_topology_mutex); |
| 1307 | port_info = mptsas_get_hba_portinfo(ioc); | 2165 | port_info = ioc->hba_port_info; |
| 1308 | if (port_info && port_info->phy_info) | 2166 | if (port_info && port_info->phy_info) |
| 1309 | sas_address = | 2167 | sas_address = |
| 1310 | port_info->phy_info[0].phy->identify.sas_address; | 2168 | port_info->phy_info[0].phy->identify.sas_address; |
| @@ -1319,26 +2177,32 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1319 | /* request */ | 2177 | /* request */ |
| 1320 | flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT | | 2178 | flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT | |
| 1321 | MPI_SGE_FLAGS_END_OF_BUFFER | | 2179 | MPI_SGE_FLAGS_END_OF_BUFFER | |
| 1322 | MPI_SGE_FLAGS_DIRECTION | | 2180 | MPI_SGE_FLAGS_DIRECTION) |
| 1323 | mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT; | 2181 | << MPI_SGE_FLAGS_SHIFT; |
| 1324 | flagsLength |= (blk_rq_bytes(req) - 4); | 2182 | flagsLength |= (blk_rq_bytes(req) - 4); |
| 1325 | 2183 | ||
| 1326 | dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio), | 2184 | dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio), |
| 1327 | blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL); | 2185 | blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL); |
| 1328 | if (!dma_addr_out) | 2186 | if (!dma_addr_out) |
| 1329 | goto put_mf; | 2187 | goto put_mf; |
| 1330 | mpt_add_sge(psge, flagsLength, dma_addr_out); | 2188 | ioc->add_sge(psge, flagsLength, dma_addr_out); |
| 1331 | psge += (sizeof(u32) + sizeof(dma_addr_t)); | 2189 | psge += ioc->SGE_size; |
| 1332 | 2190 | ||
| 1333 | /* response */ | 2191 | /* response */ |
| 1334 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; | 2192 | flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT | |
| 2193 | MPI_SGE_FLAGS_SYSTEM_ADDRESS | | ||
| 2194 | MPI_SGE_FLAGS_IOC_TO_HOST | | ||
| 2195 | MPI_SGE_FLAGS_END_OF_BUFFER; | ||
| 2196 | |||
| 2197 | flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT; | ||
| 1335 | flagsLength |= blk_rq_bytes(rsp) + 4; | 2198 | flagsLength |= blk_rq_bytes(rsp) + 4; |
| 1336 | dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio), | 2199 | dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio), |
| 1337 | blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL); | 2200 | blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL); |
| 1338 | if (!dma_addr_in) | 2201 | if (!dma_addr_in) |
| 1339 | goto unmap; | 2202 | goto unmap; |
| 1340 | mpt_add_sge(psge, flagsLength, dma_addr_in); | 2203 | ioc->add_sge(psge, flagsLength, dma_addr_in); |
| 1341 | 2204 | ||
| 2205 | INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status) | ||
| 1342 | mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf); | 2206 | mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf); |
| 1343 | 2207 | ||
| 1344 | timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ); | 2208 | timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ); |
| @@ -1351,7 +2215,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1351 | } | 2215 | } |
| 1352 | mf = NULL; | 2216 | mf = NULL; |
| 1353 | 2217 | ||
| 1354 | if (ioc->sas_mgmt.status & MPT_IOCTL_STATUS_RF_VALID) { | 2218 | if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) { |
| 1355 | SmpPassthroughReply_t *smprep; | 2219 | SmpPassthroughReply_t *smprep; |
| 1356 | 2220 | ||
| 1357 | smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply; | 2221 | smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply; |
| @@ -1360,7 +2224,8 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1360 | req->resid_len = 0; | 2224 | req->resid_len = 0; |
| 1361 | rsp->resid_len -= smprep->ResponseDataLength; | 2225 | rsp->resid_len -= smprep->ResponseDataLength; |
| 1362 | } else { | 2226 | } else { |
| 1363 | printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n", | 2227 | printk(MYIOC_s_ERR_FMT |
| 2228 | "%s: smp passthru reply failed to be returned\n", | ||
| 1364 | ioc->name, __func__); | 2229 | ioc->name, __func__); |
| 1365 | ret = -ENXIO; | 2230 | ret = -ENXIO; |
| 1366 | } | 2231 | } |
| @@ -1375,6 +2240,7 @@ put_mf: | |||
| 1375 | if (mf) | 2240 | if (mf) |
| 1376 | mpt_free_msg_frame(ioc, mf); | 2241 | mpt_free_msg_frame(ioc, mf); |
| 1377 | out_unlock: | 2242 | out_unlock: |
| 2243 | CLEAR_MGMT_STATUS(ioc->sas_mgmt.status) | ||
| 1378 | mutex_unlock(&ioc->sas_mgmt.mutex); | 2244 | mutex_unlock(&ioc->sas_mgmt.mutex); |
| 1379 | out: | 2245 | out: |
| 1380 | return ret; | 2246 | return ret; |
| @@ -1438,7 +2304,7 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) | |||
| 1438 | 2304 | ||
| 1439 | port_info->num_phys = buffer->NumPhys; | 2305 | port_info->num_phys = buffer->NumPhys; |
| 1440 | port_info->phy_info = kcalloc(port_info->num_phys, | 2306 | port_info->phy_info = kcalloc(port_info->num_phys, |
| 1441 | sizeof(*port_info->phy_info),GFP_KERNEL); | 2307 | sizeof(struct mptsas_phyinfo), GFP_KERNEL); |
| 1442 | if (!port_info->phy_info) { | 2308 | if (!port_info->phy_info) { |
| 1443 | error = -ENOMEM; | 2309 | error = -ENOMEM; |
| 1444 | goto out_free_consistent; | 2310 | goto out_free_consistent; |
| @@ -1600,10 +2466,6 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, | |||
| 1600 | __le64 sas_address; | 2466 | __le64 sas_address; |
| 1601 | int error=0; | 2467 | int error=0; |
| 1602 | 2468 | ||
| 1603 | if (ioc->sas_discovery_runtime && | ||
| 1604 | mptsas_is_end_device(device_info)) | ||
| 1605 | goto out; | ||
| 1606 | |||
| 1607 | hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION; | 2469 | hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION; |
| 1608 | hdr.ExtPageLength = 0; | 2470 | hdr.ExtPageLength = 0; |
| 1609 | hdr.PageNumber = 0; | 2471 | hdr.PageNumber = 0; |
| @@ -1644,6 +2506,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, | |||
| 1644 | 2506 | ||
| 1645 | mptsas_print_device_pg0(ioc, buffer); | 2507 | mptsas_print_device_pg0(ioc, buffer); |
| 1646 | 2508 | ||
| 2509 | memset(device_info, 0, sizeof(struct mptsas_devinfo)); | ||
| 1647 | device_info->handle = le16_to_cpu(buffer->DevHandle); | 2510 | device_info->handle = le16_to_cpu(buffer->DevHandle); |
| 1648 | device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle); | 2511 | device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle); |
| 1649 | device_info->handle_enclosure = | 2512 | device_info->handle_enclosure = |
| @@ -1675,7 +2538,9 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, | |||
| 1675 | SasExpanderPage0_t *buffer; | 2538 | SasExpanderPage0_t *buffer; |
| 1676 | dma_addr_t dma_handle; | 2539 | dma_addr_t dma_handle; |
| 1677 | int i, error; | 2540 | int i, error; |
| 2541 | __le64 sas_address; | ||
| 1678 | 2542 | ||
| 2543 | memset(port_info, 0, sizeof(struct mptsas_portinfo)); | ||
| 1679 | hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION; | 2544 | hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION; |
| 1680 | hdr.ExtPageLength = 0; | 2545 | hdr.ExtPageLength = 0; |
| 1681 | hdr.PageNumber = 0; | 2546 | hdr.PageNumber = 0; |
| @@ -1721,18 +2586,23 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, | |||
| 1721 | } | 2586 | } |
| 1722 | 2587 | ||
| 1723 | /* save config data */ | 2588 | /* save config data */ |
| 1724 | port_info->num_phys = buffer->NumPhys; | 2589 | port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1; |
| 1725 | port_info->phy_info = kcalloc(port_info->num_phys, | 2590 | port_info->phy_info = kcalloc(port_info->num_phys, |
| 1726 | sizeof(*port_info->phy_info),GFP_KERNEL); | 2591 | sizeof(struct mptsas_phyinfo), GFP_KERNEL); |
| 1727 | if (!port_info->phy_info) { | 2592 | if (!port_info->phy_info) { |
| 1728 | error = -ENOMEM; | 2593 | error = -ENOMEM; |
| 1729 | goto out_free_consistent; | 2594 | goto out_free_consistent; |
| 1730 | } | 2595 | } |
| 1731 | 2596 | ||
| 2597 | memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); | ||
| 1732 | for (i = 0; i < port_info->num_phys; i++) { | 2598 | for (i = 0; i < port_info->num_phys; i++) { |
| 1733 | port_info->phy_info[i].portinfo = port_info; | 2599 | port_info->phy_info[i].portinfo = port_info; |
| 1734 | port_info->phy_info[i].handle = | 2600 | port_info->phy_info[i].handle = |
| 1735 | le16_to_cpu(buffer->DevHandle); | 2601 | le16_to_cpu(buffer->DevHandle); |
| 2602 | port_info->phy_info[i].identify.sas_address = | ||
| 2603 | le64_to_cpu(sas_address); | ||
| 2604 | port_info->phy_info[i].identify.handle_parent = | ||
| 2605 | le16_to_cpu(buffer->ParentDevHandle); | ||
| 1736 | } | 2606 | } |
| 1737 | 2607 | ||
| 1738 | out_free_consistent: | 2608 | out_free_consistent: |
| @@ -1752,11 +2622,7 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, | |||
| 1752 | dma_addr_t dma_handle; | 2622 | dma_addr_t dma_handle; |
| 1753 | int error=0; | 2623 | int error=0; |
| 1754 | 2624 | ||
| 1755 | if (ioc->sas_discovery_runtime && | 2625 | hdr.PageVersion = MPI_SASEXPANDER1_PAGEVERSION; |
| 1756 | mptsas_is_end_device(&phy_info->attached)) | ||
| 1757 | goto out; | ||
| 1758 | |||
| 1759 | hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION; | ||
| 1760 | hdr.ExtPageLength = 0; | 2626 | hdr.ExtPageLength = 0; |
| 1761 | hdr.PageNumber = 1; | 2627 | hdr.PageNumber = 1; |
| 1762 | hdr.Reserved1 = 0; | 2628 | hdr.Reserved1 = 0; |
| @@ -1791,6 +2657,12 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, | |||
| 1791 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | 2657 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; |
| 1792 | 2658 | ||
| 1793 | error = mpt_config(ioc, &cfg); | 2659 | error = mpt_config(ioc, &cfg); |
| 2660 | |||
| 2661 | if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) { | ||
| 2662 | error = -ENODEV; | ||
| 2663 | goto out; | ||
| 2664 | } | ||
| 2665 | |||
| 1794 | if (error) | 2666 | if (error) |
| 1795 | goto out_free_consistent; | 2667 | goto out_free_consistent; |
| 1796 | 2668 | ||
| @@ -2010,16 +2882,21 @@ static int mptsas_probe_one_phy(struct device *dev, | |||
| 2010 | goto out; | 2882 | goto out; |
| 2011 | } | 2883 | } |
| 2012 | mptsas_set_port(ioc, phy_info, port); | 2884 | mptsas_set_port(ioc, phy_info, port); |
| 2013 | dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 2885 | devtprintk(ioc, dev_printk(KERN_DEBUG, &port->dev, |
| 2014 | "sas_port_alloc: port=%p dev=%p port_id=%d\n", | 2886 | MYIOC_s_FMT "add port %d, sas_addr (0x%llx)\n", |
| 2015 | ioc->name, port, dev, port->port_identifier)); | 2887 | ioc->name, port->port_identifier, |
| 2888 | (unsigned long long)phy_info-> | ||
| 2889 | attached.sas_address)); | ||
| 2016 | } | 2890 | } |
| 2017 | dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n", | 2891 | dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2018 | ioc->name, phy_info->phy_id)); | 2892 | "sas_port_add_phy: phy_id=%d\n", |
| 2893 | ioc->name, phy_info->phy_id)); | ||
| 2019 | sas_port_add_phy(port, phy_info->phy); | 2894 | sas_port_add_phy(port, phy_info->phy); |
| 2020 | phy_info->sas_port_add_phy = 0; | 2895 | phy_info->sas_port_add_phy = 0; |
| 2896 | devtprintk(ioc, dev_printk(KERN_DEBUG, &phy_info->phy->dev, | ||
| 2897 | MYIOC_s_FMT "add phy %d, phy-obj (0x%p)\n", ioc->name, | ||
| 2898 | phy_info->phy_id, phy_info->phy)); | ||
| 2021 | } | 2899 | } |
| 2022 | |||
| 2023 | if (!mptsas_get_rphy(phy_info) && port && !port->rphy) { | 2900 | if (!mptsas_get_rphy(phy_info) && port && !port->rphy) { |
| 2024 | 2901 | ||
| 2025 | struct sas_rphy *rphy; | 2902 | struct sas_rphy *rphy; |
| @@ -2032,18 +2909,17 @@ static int mptsas_probe_one_phy(struct device *dev, | |||
| 2032 | * the adding/removing of devices that occur | 2909 | * the adding/removing of devices that occur |
| 2033 | * after start of day. | 2910 | * after start of day. |
| 2034 | */ | 2911 | */ |
| 2035 | if (ioc->sas_discovery_runtime && | 2912 | if (mptsas_is_end_device(&phy_info->attached) && |
| 2036 | mptsas_is_end_device(&phy_info->attached)) | 2913 | phy_info->attached.handle_parent) { |
| 2037 | goto out; | 2914 | goto out; |
| 2915 | } | ||
| 2038 | 2916 | ||
| 2039 | mptsas_parse_device_info(&identify, &phy_info->attached); | 2917 | mptsas_parse_device_info(&identify, &phy_info->attached); |
| 2040 | if (scsi_is_host_device(parent)) { | 2918 | if (scsi_is_host_device(parent)) { |
| 2041 | struct mptsas_portinfo *port_info; | 2919 | struct mptsas_portinfo *port_info; |
| 2042 | int i; | 2920 | int i; |
| 2043 | 2921 | ||
| 2044 | mutex_lock(&ioc->sas_topology_mutex); | 2922 | port_info = ioc->hba_port_info; |
| 2045 | port_info = mptsas_get_hba_portinfo(ioc); | ||
| 2046 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 2047 | 2923 | ||
| 2048 | for (i = 0; i < port_info->num_phys; i++) | 2924 | for (i = 0; i < port_info->num_phys; i++) |
| 2049 | if (port_info->phy_info[i].identify.sas_address == | 2925 | if (port_info->phy_info[i].identify.sas_address == |
| @@ -2102,7 +2978,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) | |||
| 2102 | struct mptsas_portinfo *port_info, *hba; | 2978 | struct mptsas_portinfo *port_info, *hba; |
| 2103 | int error = -ENOMEM, i; | 2979 | int error = -ENOMEM, i; |
| 2104 | 2980 | ||
| 2105 | hba = kzalloc(sizeof(*port_info), GFP_KERNEL); | 2981 | hba = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL); |
| 2106 | if (! hba) | 2982 | if (! hba) |
| 2107 | goto out; | 2983 | goto out; |
| 2108 | 2984 | ||
| @@ -2112,9 +2988,10 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) | |||
| 2112 | 2988 | ||
| 2113 | mptsas_sas_io_unit_pg1(ioc); | 2989 | mptsas_sas_io_unit_pg1(ioc); |
| 2114 | mutex_lock(&ioc->sas_topology_mutex); | 2990 | mutex_lock(&ioc->sas_topology_mutex); |
| 2115 | port_info = mptsas_get_hba_portinfo(ioc); | 2991 | port_info = ioc->hba_port_info; |
| 2116 | if (!port_info) { | 2992 | if (!port_info) { |
| 2117 | port_info = hba; | 2993 | ioc->hba_port_info = port_info = hba; |
| 2994 | ioc->hba_port_num_phy = port_info->num_phys; | ||
| 2118 | list_add_tail(&port_info->list, &ioc->sas_topology); | 2995 | list_add_tail(&port_info->list, &ioc->sas_topology); |
| 2119 | } else { | 2996 | } else { |
| 2120 | for (i = 0; i < hba->num_phys; i++) { | 2997 | for (i = 0; i < hba->num_phys; i++) { |
| @@ -2130,15 +3007,22 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) | |||
| 2130 | hba = NULL; | 3007 | hba = NULL; |
| 2131 | } | 3008 | } |
| 2132 | mutex_unlock(&ioc->sas_topology_mutex); | 3009 | mutex_unlock(&ioc->sas_topology_mutex); |
| 3010 | #if defined(CPQ_CIM) | ||
| 3011 | ioc->num_ports = port_info->num_phys; | ||
| 3012 | #endif | ||
| 2133 | for (i = 0; i < port_info->num_phys; i++) { | 3013 | for (i = 0; i < port_info->num_phys; i++) { |
| 2134 | mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], | 3014 | mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], |
| 2135 | (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << | 3015 | (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << |
| 2136 | MPI_SAS_PHY_PGAD_FORM_SHIFT), i); | 3016 | MPI_SAS_PHY_PGAD_FORM_SHIFT), i); |
| 2137 | 3017 | port_info->phy_info[i].identify.handle = | |
| 3018 | port_info->phy_info[i].handle; | ||
| 2138 | mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify, | 3019 | mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify, |
| 2139 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << | 3020 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << |
| 2140 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | 3021 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), |
| 2141 | port_info->phy_info[i].handle); | 3022 | port_info->phy_info[i].identify.handle); |
| 3023 | if (!ioc->hba_port_sas_addr) | ||
| 3024 | ioc->hba_port_sas_addr = | ||
| 3025 | port_info->phy_info[i].identify.sas_address; | ||
| 2142 | port_info->phy_info[i].identify.phy_id = | 3026 | port_info->phy_info[i].identify.phy_id = |
| 2143 | port_info->phy_info[i].phy_id = i; | 3027 | port_info->phy_info[i].phy_id = i; |
| 2144 | if (port_info->phy_info[i].attached.handle) | 3028 | if (port_info->phy_info[i].attached.handle) |
| @@ -2163,248 +3047,721 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) | |||
| 2163 | return error; | 3047 | return error; |
| 2164 | } | 3048 | } |
| 2165 | 3049 | ||
| 2166 | static int | 3050 | static void |
| 2167 | mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) | 3051 | mptsas_expander_refresh(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) |
| 2168 | { | 3052 | { |
| 2169 | struct mptsas_portinfo *port_info, *p, *ex; | 3053 | struct mptsas_portinfo *parent; |
| 2170 | struct device *parent; | 3054 | struct device *parent_dev; |
| 2171 | struct sas_rphy *rphy; | 3055 | struct sas_rphy *rphy; |
| 2172 | int error = -ENOMEM, i, j; | 3056 | int i; |
| 2173 | 3057 | u64 sas_address; /* expander sas address */ | |
| 2174 | ex = kzalloc(sizeof(*port_info), GFP_KERNEL); | 3058 | u32 handle; |
| 2175 | if (!ex) | 3059 | |
| 2176 | goto out; | 3060 | handle = port_info->phy_info[0].handle; |
| 2177 | 3061 | sas_address = port_info->phy_info[0].identify.sas_address; | |
| 2178 | error = mptsas_sas_expander_pg0(ioc, ex, | ||
| 2179 | (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << | ||
| 2180 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); | ||
| 2181 | if (error) | ||
| 2182 | goto out_free_port_info; | ||
| 2183 | |||
| 2184 | *handle = ex->phy_info[0].handle; | ||
| 2185 | |||
| 2186 | mutex_lock(&ioc->sas_topology_mutex); | ||
| 2187 | port_info = mptsas_find_portinfo_by_handle(ioc, *handle); | ||
| 2188 | if (!port_info) { | ||
| 2189 | port_info = ex; | ||
| 2190 | list_add_tail(&port_info->list, &ioc->sas_topology); | ||
| 2191 | } else { | ||
| 2192 | for (i = 0; i < ex->num_phys; i++) { | ||
| 2193 | port_info->phy_info[i].handle = | ||
| 2194 | ex->phy_info[i].handle; | ||
| 2195 | port_info->phy_info[i].port_id = | ||
| 2196 | ex->phy_info[i].port_id; | ||
| 2197 | } | ||
| 2198 | kfree(ex->phy_info); | ||
| 2199 | kfree(ex); | ||
| 2200 | ex = NULL; | ||
| 2201 | } | ||
| 2202 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 2203 | |||
| 2204 | for (i = 0; i < port_info->num_phys; i++) { | 3062 | for (i = 0; i < port_info->num_phys; i++) { |
| 2205 | mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i], | 3063 | mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i], |
| 2206 | (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM << | 3064 | (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM << |
| 2207 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle); | 3065 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + handle); |
| 2208 | 3066 | ||
| 2209 | if (port_info->phy_info[i].identify.handle) { | 3067 | mptsas_sas_device_pg0(ioc, |
| 2210 | mptsas_sas_device_pg0(ioc, | 3068 | &port_info->phy_info[i].identify, |
| 2211 | &port_info->phy_info[i].identify, | 3069 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << |
| 2212 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << | 3070 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), |
| 2213 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | 3071 | port_info->phy_info[i].identify.handle); |
| 2214 | port_info->phy_info[i].identify.handle); | 3072 | port_info->phy_info[i].identify.phy_id = |
| 2215 | port_info->phy_info[i].identify.phy_id = | 3073 | port_info->phy_info[i].phy_id; |
| 2216 | port_info->phy_info[i].phy_id; | ||
| 2217 | } | ||
| 2218 | 3074 | ||
| 2219 | if (port_info->phy_info[i].attached.handle) { | 3075 | if (port_info->phy_info[i].attached.handle) { |
| 2220 | mptsas_sas_device_pg0(ioc, | 3076 | mptsas_sas_device_pg0(ioc, |
| 2221 | &port_info->phy_info[i].attached, | 3077 | &port_info->phy_info[i].attached, |
| 2222 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << | 3078 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << |
| 2223 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | 3079 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), |
| 2224 | port_info->phy_info[i].attached.handle); | 3080 | port_info->phy_info[i].attached.handle); |
| 2225 | port_info->phy_info[i].attached.phy_id = | 3081 | port_info->phy_info[i].attached.phy_id = |
| 2226 | port_info->phy_info[i].phy_id; | 3082 | port_info->phy_info[i].phy_id; |
| 2227 | } | 3083 | } |
| 2228 | } | 3084 | } |
| 2229 | 3085 | ||
| 2230 | parent = &ioc->sh->shost_gendev; | 3086 | mutex_lock(&ioc->sas_topology_mutex); |
| 2231 | for (i = 0; i < port_info->num_phys; i++) { | 3087 | parent = mptsas_find_portinfo_by_handle(ioc, |
| 2232 | mutex_lock(&ioc->sas_topology_mutex); | 3088 | port_info->phy_info[0].identify.handle_parent); |
| 2233 | list_for_each_entry(p, &ioc->sas_topology, list) { | 3089 | if (!parent) { |
| 2234 | for (j = 0; j < p->num_phys; j++) { | ||
| 2235 | if (port_info->phy_info[i].identify.handle != | ||
| 2236 | p->phy_info[j].attached.handle) | ||
| 2237 | continue; | ||
| 2238 | rphy = mptsas_get_rphy(&p->phy_info[j]); | ||
| 2239 | parent = &rphy->dev; | ||
| 2240 | } | ||
| 2241 | } | ||
| 2242 | mutex_unlock(&ioc->sas_topology_mutex); | 3090 | mutex_unlock(&ioc->sas_topology_mutex); |
| 3091 | return; | ||
| 2243 | } | 3092 | } |
| 3093 | for (i = 0, parent_dev = NULL; i < parent->num_phys && !parent_dev; | ||
| 3094 | i++) { | ||
| 3095 | if (parent->phy_info[i].attached.sas_address == sas_address) { | ||
| 3096 | rphy = mptsas_get_rphy(&parent->phy_info[i]); | ||
| 3097 | parent_dev = &rphy->dev; | ||
| 3098 | } | ||
| 3099 | } | ||
| 3100 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 2244 | 3101 | ||
| 2245 | mptsas_setup_wide_ports(ioc, port_info); | 3102 | mptsas_setup_wide_ports(ioc, port_info); |
| 2246 | |||
| 2247 | for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++) | 3103 | for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++) |
| 2248 | mptsas_probe_one_phy(parent, &port_info->phy_info[i], | 3104 | mptsas_probe_one_phy(parent_dev, &port_info->phy_info[i], |
| 2249 | ioc->sas_index, 0); | 3105 | ioc->sas_index, 0); |
| 3106 | } | ||
| 2250 | 3107 | ||
| 2251 | return 0; | 3108 | static void |
| 3109 | mptsas_expander_event_add(MPT_ADAPTER *ioc, | ||
| 3110 | MpiEventDataSasExpanderStatusChange_t *expander_data) | ||
| 3111 | { | ||
| 3112 | struct mptsas_portinfo *port_info; | ||
| 3113 | int i; | ||
| 3114 | __le64 sas_address; | ||
| 2252 | 3115 | ||
| 2253 | out_free_port_info: | 3116 | port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL); |
| 2254 | if (ex) { | 3117 | if (!port_info) |
| 2255 | kfree(ex->phy_info); | 3118 | BUG(); |
| 2256 | kfree(ex); | 3119 | port_info->num_phys = (expander_data->NumPhys) ? |
| 3120 | expander_data->NumPhys : 1; | ||
| 3121 | port_info->phy_info = kcalloc(port_info->num_phys, | ||
| 3122 | sizeof(struct mptsas_phyinfo), GFP_KERNEL); | ||
| 3123 | if (!port_info->phy_info) | ||
| 3124 | BUG(); | ||
| 3125 | memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64)); | ||
| 3126 | for (i = 0; i < port_info->num_phys; i++) { | ||
| 3127 | port_info->phy_info[i].portinfo = port_info; | ||
| 3128 | port_info->phy_info[i].handle = | ||
| 3129 | le16_to_cpu(expander_data->DevHandle); | ||
| 3130 | port_info->phy_info[i].identify.sas_address = | ||
| 3131 | le64_to_cpu(sas_address); | ||
| 3132 | port_info->phy_info[i].identify.handle_parent = | ||
| 3133 | le16_to_cpu(expander_data->ParentDevHandle); | ||
| 3134 | } | ||
| 3135 | |||
| 3136 | mutex_lock(&ioc->sas_topology_mutex); | ||
| 3137 | list_add_tail(&port_info->list, &ioc->sas_topology); | ||
| 3138 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 3139 | |||
| 3140 | printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, " | ||
| 3141 | "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys, | ||
| 3142 | (unsigned long long)sas_address); | ||
| 3143 | |||
| 3144 | mptsas_expander_refresh(ioc, port_info); | ||
| 3145 | } | ||
| 3146 | |||
| 3147 | /** | ||
| 3148 | * mptsas_delete_expander_siblings - remove siblings attached to expander | ||
| 3149 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 3150 | * @parent: the parent port_info object | ||
| 3151 | * @expander: the expander port_info object | ||
| 3152 | **/ | ||
| 3153 | static void | ||
| 3154 | mptsas_delete_expander_siblings(MPT_ADAPTER *ioc, struct mptsas_portinfo | ||
| 3155 | *parent, struct mptsas_portinfo *expander) | ||
| 3156 | { | ||
| 3157 | struct mptsas_phyinfo *phy_info; | ||
| 3158 | struct mptsas_portinfo *port_info; | ||
| 3159 | struct sas_rphy *rphy; | ||
| 3160 | int i; | ||
| 3161 | |||
| 3162 | phy_info = expander->phy_info; | ||
| 3163 | for (i = 0; i < expander->num_phys; i++, phy_info++) { | ||
| 3164 | rphy = mptsas_get_rphy(phy_info); | ||
| 3165 | if (!rphy) | ||
| 3166 | continue; | ||
| 3167 | if (rphy->identify.device_type == SAS_END_DEVICE) | ||
| 3168 | mptsas_del_end_device(ioc, phy_info); | ||
| 3169 | } | ||
| 3170 | |||
| 3171 | phy_info = expander->phy_info; | ||
| 3172 | for (i = 0; i < expander->num_phys; i++, phy_info++) { | ||
| 3173 | rphy = mptsas_get_rphy(phy_info); | ||
| 3174 | if (!rphy) | ||
| 3175 | continue; | ||
| 3176 | if (rphy->identify.device_type == | ||
| 3177 | MPI_SAS_DEVICE_INFO_EDGE_EXPANDER || | ||
| 3178 | rphy->identify.device_type == | ||
| 3179 | MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) { | ||
| 3180 | port_info = mptsas_find_portinfo_by_sas_address(ioc, | ||
| 3181 | rphy->identify.sas_address); | ||
| 3182 | if (!port_info) | ||
| 3183 | continue; | ||
| 3184 | if (port_info == parent) /* backlink rphy */ | ||
| 3185 | continue; | ||
| 3186 | /* | ||
| 3187 | Delete this expander even if the expdevpage is exists | ||
| 3188 | because the parent expander is already deleted | ||
| 3189 | */ | ||
| 3190 | mptsas_expander_delete(ioc, port_info, 1); | ||
| 3191 | } | ||
| 3192 | } | ||
| 3193 | } | ||
| 3194 | |||
| 3195 | |||
| 3196 | /** | ||
| 3197 | * mptsas_expander_delete - remove this expander | ||
| 3198 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 3199 | * @port_info: expander port_info struct | ||
| 3200 | * @force: Flag to forcefully delete the expander | ||
| 3201 | * | ||
| 3202 | **/ | ||
| 3203 | |||
| 3204 | static void mptsas_expander_delete(MPT_ADAPTER *ioc, | ||
| 3205 | struct mptsas_portinfo *port_info, u8 force) | ||
| 3206 | { | ||
| 3207 | |||
| 3208 | struct mptsas_portinfo *parent; | ||
| 3209 | int i; | ||
| 3210 | u64 expander_sas_address; | ||
| 3211 | struct mptsas_phyinfo *phy_info; | ||
| 3212 | struct mptsas_portinfo buffer; | ||
| 3213 | struct mptsas_portinfo_details *port_details; | ||
| 3214 | struct sas_port *port; | ||
| 3215 | |||
| 3216 | if (!port_info) | ||
| 3217 | return; | ||
| 3218 | |||
| 3219 | /* see if expander is still there before deleting */ | ||
| 3220 | mptsas_sas_expander_pg0(ioc, &buffer, | ||
| 3221 | (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << | ||
| 3222 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), | ||
| 3223 | port_info->phy_info[0].identify.handle); | ||
| 3224 | |||
| 3225 | if (buffer.num_phys) { | ||
| 3226 | kfree(buffer.phy_info); | ||
| 3227 | if (!force) | ||
| 3228 | return; | ||
| 3229 | } | ||
| 3230 | |||
| 3231 | |||
| 3232 | /* | ||
| 3233 | * Obtain the port_info instance to the parent port | ||
| 3234 | */ | ||
| 3235 | port_details = NULL; | ||
| 3236 | expander_sas_address = | ||
| 3237 | port_info->phy_info[0].identify.sas_address; | ||
| 3238 | parent = mptsas_find_portinfo_by_handle(ioc, | ||
| 3239 | port_info->phy_info[0].identify.handle_parent); | ||
| 3240 | mptsas_delete_expander_siblings(ioc, parent, port_info); | ||
| 3241 | if (!parent) | ||
| 3242 | goto out; | ||
| 3243 | |||
| 3244 | /* | ||
| 3245 | * Delete rphys in the parent that point | ||
| 3246 | * to this expander. | ||
| 3247 | */ | ||
| 3248 | phy_info = parent->phy_info; | ||
| 3249 | port = NULL; | ||
| 3250 | for (i = 0; i < parent->num_phys; i++, phy_info++) { | ||
| 3251 | if (!phy_info->phy) | ||
| 3252 | continue; | ||
| 3253 | if (phy_info->attached.sas_address != | ||
| 3254 | expander_sas_address) | ||
| 3255 | continue; | ||
| 3256 | if (!port) { | ||
| 3257 | port = mptsas_get_port(phy_info); | ||
| 3258 | port_details = phy_info->port_details; | ||
| 3259 | } | ||
| 3260 | dev_printk(KERN_DEBUG, &phy_info->phy->dev, | ||
| 3261 | MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name, | ||
| 3262 | phy_info->phy_id, phy_info->phy); | ||
| 3263 | sas_port_delete_phy(port, phy_info->phy); | ||
| 3264 | } | ||
| 3265 | if (port) { | ||
| 3266 | dev_printk(KERN_DEBUG, &port->dev, | ||
| 3267 | MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n", | ||
| 3268 | ioc->name, port->port_identifier, | ||
| 3269 | (unsigned long long)expander_sas_address); | ||
| 3270 | sas_port_delete(port); | ||
| 3271 | mptsas_port_delete(ioc, port_details); | ||
| 2257 | } | 3272 | } |
| 2258 | out: | 3273 | out: |
| 2259 | return error; | 3274 | |
| 3275 | printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, " | ||
| 3276 | "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys, | ||
| 3277 | (unsigned long long)expander_sas_address); | ||
| 3278 | |||
| 3279 | /* | ||
| 3280 | * free link | ||
| 3281 | */ | ||
| 3282 | list_del(&port_info->list); | ||
| 3283 | kfree(port_info->phy_info); | ||
| 3284 | kfree(port_info); | ||
| 2260 | } | 3285 | } |
| 2261 | 3286 | ||
| 2262 | /* | 3287 | |
| 2263 | * mptsas_delete_expander_phys | 3288 | /** |
| 3289 | * mptsas_send_expander_event - expanders events | ||
| 3290 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 3291 | * @expander_data: event data | ||
| 2264 | * | 3292 | * |
| 2265 | * | 3293 | * |
| 2266 | * This will traverse topology, and remove expanders | 3294 | * This function handles adding, removing, and refreshing |
| 2267 | * that are no longer present | 3295 | * device handles within the expander objects. |
| 2268 | */ | 3296 | */ |
| 2269 | static void | 3297 | static void |
| 2270 | mptsas_delete_expander_phys(MPT_ADAPTER *ioc) | 3298 | mptsas_send_expander_event(struct fw_event_work *fw_event) |
| 2271 | { | 3299 | { |
| 2272 | struct mptsas_portinfo buffer; | 3300 | MPT_ADAPTER *ioc; |
| 2273 | struct mptsas_portinfo *port_info, *n, *parent; | 3301 | MpiEventDataSasExpanderStatusChange_t *expander_data; |
| 2274 | struct mptsas_phyinfo *phy_info; | 3302 | struct mptsas_portinfo *port_info; |
| 2275 | struct sas_port * port; | 3303 | __le64 sas_address; |
| 2276 | int i; | 3304 | int i; |
| 2277 | u64 expander_sas_address; | ||
| 2278 | 3305 | ||
| 3306 | ioc = fw_event->ioc; | ||
| 3307 | expander_data = (MpiEventDataSasExpanderStatusChange_t *) | ||
| 3308 | fw_event->event_data; | ||
| 3309 | memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64)); | ||
| 3310 | port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address); | ||
| 3311 | |||
| 3312 | if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) { | ||
| 3313 | if (port_info) { | ||
| 3314 | for (i = 0; i < port_info->num_phys; i++) { | ||
| 3315 | port_info->phy_info[i].portinfo = port_info; | ||
| 3316 | port_info->phy_info[i].handle = | ||
| 3317 | le16_to_cpu(expander_data->DevHandle); | ||
| 3318 | port_info->phy_info[i].identify.sas_address = | ||
| 3319 | le64_to_cpu(sas_address); | ||
| 3320 | port_info->phy_info[i].identify.handle_parent = | ||
| 3321 | le16_to_cpu(expander_data->ParentDevHandle); | ||
| 3322 | } | ||
| 3323 | mptsas_expander_refresh(ioc, port_info); | ||
| 3324 | } else if (!port_info && expander_data->NumPhys) | ||
| 3325 | mptsas_expander_event_add(ioc, expander_data); | ||
| 3326 | } else if (expander_data->ReasonCode == | ||
| 3327 | MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING) | ||
| 3328 | mptsas_expander_delete(ioc, port_info, 0); | ||
| 3329 | |||
| 3330 | mptsas_free_fw_event(ioc, fw_event); | ||
| 3331 | } | ||
| 3332 | |||
| 3333 | |||
| 3334 | /** | ||
| 3335 | * mptsas_expander_add - | ||
| 3336 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 3337 | * @handle: | ||
| 3338 | * | ||
| 3339 | */ | ||
| 3340 | struct mptsas_portinfo * | ||
| 3341 | mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle) | ||
| 3342 | { | ||
| 3343 | struct mptsas_portinfo buffer, *port_info; | ||
| 3344 | int i; | ||
| 3345 | |||
| 3346 | if ((mptsas_sas_expander_pg0(ioc, &buffer, | ||
| 3347 | (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << | ||
| 3348 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle))) | ||
| 3349 | return NULL; | ||
| 3350 | |||
| 3351 | port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_ATOMIC); | ||
| 3352 | if (!port_info) { | ||
| 3353 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 3354 | "%s: exit at line=%d\n", ioc->name, | ||
| 3355 | __func__, __LINE__)); | ||
| 3356 | return NULL; | ||
| 3357 | } | ||
| 3358 | port_info->num_phys = buffer.num_phys; | ||
| 3359 | port_info->phy_info = buffer.phy_info; | ||
| 3360 | for (i = 0; i < port_info->num_phys; i++) | ||
| 3361 | port_info->phy_info[i].portinfo = port_info; | ||
| 2279 | mutex_lock(&ioc->sas_topology_mutex); | 3362 | mutex_lock(&ioc->sas_topology_mutex); |
| 2280 | list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) { | 3363 | list_add_tail(&port_info->list, &ioc->sas_topology); |
| 3364 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 3365 | printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, " | ||
| 3366 | "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys, | ||
| 3367 | (unsigned long long)buffer.phy_info[0].identify.sas_address); | ||
| 3368 | mptsas_expander_refresh(ioc, port_info); | ||
| 3369 | return port_info; | ||
| 3370 | } | ||
| 2281 | 3371 | ||
| 2282 | if (!(port_info->phy_info[0].identify.device_info & | 3372 | static void |
| 2283 | MPI_SAS_DEVICE_INFO_SMP_TARGET)) | 3373 | mptsas_send_link_status_event(struct fw_event_work *fw_event) |
| 3374 | { | ||
| 3375 | MPT_ADAPTER *ioc; | ||
| 3376 | MpiEventDataSasPhyLinkStatus_t *link_data; | ||
| 3377 | struct mptsas_portinfo *port_info; | ||
| 3378 | struct mptsas_phyinfo *phy_info = NULL; | ||
| 3379 | __le64 sas_address; | ||
| 3380 | u8 phy_num; | ||
| 3381 | u8 link_rate; | ||
| 3382 | |||
| 3383 | ioc = fw_event->ioc; | ||
| 3384 | link_data = (MpiEventDataSasPhyLinkStatus_t *)fw_event->event_data; | ||
| 3385 | |||
| 3386 | memcpy(&sas_address, &link_data->SASAddress, sizeof(__le64)); | ||
| 3387 | sas_address = le64_to_cpu(sas_address); | ||
| 3388 | link_rate = link_data->LinkRates >> 4; | ||
| 3389 | phy_num = link_data->PhyNum; | ||
| 3390 | |||
| 3391 | port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address); | ||
| 3392 | if (port_info) { | ||
| 3393 | phy_info = &port_info->phy_info[phy_num]; | ||
| 3394 | if (phy_info) | ||
| 3395 | phy_info->negotiated_link_rate = link_rate; | ||
| 3396 | } | ||
| 3397 | |||
| 3398 | if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 || | ||
| 3399 | link_rate == MPI_SAS_IOUNIT0_RATE_3_0) { | ||
| 3400 | |||
| 3401 | if (!port_info) { | ||
| 3402 | if (ioc->old_sas_discovery_protocal) { | ||
| 3403 | port_info = mptsas_expander_add(ioc, | ||
| 3404 | le16_to_cpu(link_data->DevHandle)); | ||
| 3405 | if (port_info) | ||
| 3406 | goto out; | ||
| 3407 | } | ||
| 3408 | goto out; | ||
| 3409 | } | ||
| 3410 | |||
| 3411 | if (port_info == ioc->hba_port_info) | ||
| 3412 | mptsas_probe_hba_phys(ioc); | ||
| 3413 | else | ||
| 3414 | mptsas_expander_refresh(ioc, port_info); | ||
| 3415 | } else if (phy_info && phy_info->phy) { | ||
| 3416 | if (link_rate == MPI_SAS_IOUNIT0_RATE_PHY_DISABLED) | ||
| 3417 | phy_info->phy->negotiated_linkrate = | ||
| 3418 | SAS_PHY_DISABLED; | ||
| 3419 | else if (link_rate == | ||
| 3420 | MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION) | ||
| 3421 | phy_info->phy->negotiated_linkrate = | ||
| 3422 | SAS_LINK_RATE_FAILED; | ||
| 3423 | else | ||
| 3424 | phy_info->phy->negotiated_linkrate = | ||
| 3425 | SAS_LINK_RATE_UNKNOWN; | ||
| 3426 | } | ||
| 3427 | out: | ||
| 3428 | mptsas_free_fw_event(ioc, fw_event); | ||
| 3429 | } | ||
| 3430 | |||
| 3431 | static void | ||
| 3432 | mptsas_not_responding_devices(MPT_ADAPTER *ioc) | ||
| 3433 | { | ||
| 3434 | struct mptsas_portinfo buffer, *port_info; | ||
| 3435 | struct mptsas_device_info *sas_info; | ||
| 3436 | struct mptsas_devinfo sas_device; | ||
| 3437 | u32 handle; | ||
| 3438 | VirtTarget *vtarget = NULL; | ||
| 3439 | struct mptsas_phyinfo *phy_info; | ||
| 3440 | u8 found_expander; | ||
| 3441 | int retval, retry_count; | ||
| 3442 | unsigned long flags; | ||
| 3443 | |||
| 3444 | mpt_findImVolumes(ioc); | ||
| 3445 | |||
| 3446 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
| 3447 | if (ioc->ioc_reset_in_progress) { | ||
| 3448 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 3449 | "%s: exiting due to a parallel reset \n", ioc->name, | ||
| 3450 | __func__)); | ||
| 3451 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 3452 | return; | ||
| 3453 | } | ||
| 3454 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 3455 | |||
| 3456 | /* devices, logical volumes */ | ||
| 3457 | mutex_lock(&ioc->sas_device_info_mutex); | ||
| 3458 | redo_device_scan: | ||
| 3459 | list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) { | ||
| 3460 | if (sas_info->is_cached) | ||
| 2284 | continue; | 3461 | continue; |
| 3462 | if (!sas_info->is_logical_volume) { | ||
| 3463 | sas_device.handle = 0; | ||
| 3464 | retry_count = 0; | ||
| 3465 | retry_page: | ||
| 3466 | retval = mptsas_sas_device_pg0(ioc, &sas_device, | ||
| 3467 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID | ||
| 3468 | << MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||
| 3469 | (sas_info->fw.channel << 8) + | ||
| 3470 | sas_info->fw.id); | ||
| 3471 | |||
| 3472 | if (sas_device.handle) | ||
| 3473 | continue; | ||
| 3474 | if (retval == -EBUSY) { | ||
| 3475 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
| 3476 | if (ioc->ioc_reset_in_progress) { | ||
| 3477 | dfailprintk(ioc, | ||
| 3478 | printk(MYIOC_s_DEBUG_FMT | ||
| 3479 | "%s: exiting due to reset\n", | ||
| 3480 | ioc->name, __func__)); | ||
| 3481 | spin_unlock_irqrestore | ||
| 3482 | (&ioc->taskmgmt_lock, flags); | ||
| 3483 | mutex_unlock(&ioc-> | ||
| 3484 | sas_device_info_mutex); | ||
| 3485 | return; | ||
| 3486 | } | ||
| 3487 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, | ||
| 3488 | flags); | ||
| 3489 | } | ||
| 2285 | 3490 | ||
| 2286 | if (mptsas_sas_expander_pg0(ioc, &buffer, | 3491 | if (retval && (retval != -ENODEV)) { |
| 2287 | (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << | 3492 | if (retry_count < 10) { |
| 2288 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), | 3493 | retry_count++; |
| 2289 | port_info->phy_info[0].handle)) { | 3494 | goto retry_page; |
| 3495 | } else { | ||
| 3496 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 3497 | "%s: Config page retry exceeded retry " | ||
| 3498 | "count deleting device 0x%llx\n", | ||
| 3499 | ioc->name, __func__, | ||
| 3500 | sas_info->sas_address)); | ||
| 3501 | } | ||
| 3502 | } | ||
| 2290 | 3503 | ||
| 2291 | /* | 3504 | /* delete device */ |
| 2292 | * Obtain the port_info instance to the parent port | 3505 | vtarget = mptsas_find_vtarget(ioc, |
| 2293 | */ | 3506 | sas_info->fw.channel, sas_info->fw.id); |
| 2294 | parent = mptsas_find_portinfo_by_handle(ioc, | ||
| 2295 | port_info->phy_info[0].identify.handle_parent); | ||
| 2296 | 3507 | ||
| 2297 | if (!parent) | 3508 | if (vtarget) |
| 2298 | goto next_port; | 3509 | vtarget->deleted = 1; |
| 2299 | 3510 | ||
| 2300 | expander_sas_address = | 3511 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, |
| 2301 | port_info->phy_info[0].identify.sas_address; | 3512 | sas_info->sas_address); |
| 2302 | 3513 | ||
| 2303 | /* | 3514 | if (phy_info) { |
| 2304 | * Delete rphys in the parent that point | 3515 | mptsas_del_end_device(ioc, phy_info); |
| 2305 | * to this expander. The transport layer will | 3516 | goto redo_device_scan; |
| 2306 | * cleanup all the children. | ||
| 2307 | */ | ||
| 2308 | phy_info = parent->phy_info; | ||
| 2309 | for (i = 0; i < parent->num_phys; i++, phy_info++) { | ||
| 2310 | port = mptsas_get_port(phy_info); | ||
| 2311 | if (!port) | ||
| 2312 | continue; | ||
| 2313 | if (phy_info->attached.sas_address != | ||
| 2314 | expander_sas_address) | ||
| 2315 | continue; | ||
| 2316 | dsaswideprintk(ioc, | ||
| 2317 | dev_printk(KERN_DEBUG, &port->dev, | ||
| 2318 | MYIOC_s_FMT "delete port (%d)\n", ioc->name, | ||
| 2319 | port->port_identifier)); | ||
| 2320 | sas_port_delete(port); | ||
| 2321 | mptsas_port_delete(ioc, phy_info->port_details); | ||
| 2322 | } | 3517 | } |
| 2323 | next_port: | 3518 | } else |
| 3519 | mptsas_volume_delete(ioc, sas_info->fw.id); | ||
| 3520 | } | ||
| 3521 | mutex_lock(&ioc->sas_device_info_mutex); | ||
| 2324 | 3522 | ||
| 2325 | phy_info = port_info->phy_info; | 3523 | /* expanders */ |
| 2326 | for (i = 0; i < port_info->num_phys; i++, phy_info++) | 3524 | mutex_lock(&ioc->sas_topology_mutex); |
| 2327 | mptsas_port_delete(ioc, phy_info->port_details); | 3525 | redo_expander_scan: |
| 3526 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | ||
| 2328 | 3527 | ||
| 2329 | list_del(&port_info->list); | 3528 | if (port_info->phy_info && |
| 2330 | kfree(port_info->phy_info); | 3529 | (!(port_info->phy_info[0].identify.device_info & |
| 2331 | kfree(port_info); | 3530 | MPI_SAS_DEVICE_INFO_SMP_TARGET))) |
| 3531 | continue; | ||
| 3532 | found_expander = 0; | ||
| 3533 | handle = 0xFFFF; | ||
| 3534 | while (!mptsas_sas_expander_pg0(ioc, &buffer, | ||
| 3535 | (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << | ||
| 3536 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle) && | ||
| 3537 | !found_expander) { | ||
| 3538 | |||
| 3539 | handle = buffer.phy_info[0].handle; | ||
| 3540 | if (buffer.phy_info[0].identify.sas_address == | ||
| 3541 | port_info->phy_info[0].identify.sas_address) { | ||
| 3542 | found_expander = 1; | ||
| 3543 | } | ||
| 3544 | kfree(buffer.phy_info); | ||
| 3545 | } | ||
| 3546 | |||
| 3547 | if (!found_expander) { | ||
| 3548 | mptsas_expander_delete(ioc, port_info, 0); | ||
| 3549 | goto redo_expander_scan; | ||
| 2332 | } | 3550 | } |
| 2333 | /* | ||
| 2334 | * Free this memory allocated from inside | ||
| 2335 | * mptsas_sas_expander_pg0 | ||
| 2336 | */ | ||
| 2337 | kfree(buffer.phy_info); | ||
| 2338 | } | 3551 | } |
| 2339 | mutex_unlock(&ioc->sas_topology_mutex); | 3552 | mutex_lock(&ioc->sas_topology_mutex); |
| 3553 | } | ||
| 3554 | |||
| 3555 | /** | ||
| 3556 | * mptsas_probe_expanders - adding expanders | ||
| 3557 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 3558 | * | ||
| 3559 | **/ | ||
| 3560 | static void | ||
| 3561 | mptsas_probe_expanders(MPT_ADAPTER *ioc) | ||
| 3562 | { | ||
| 3563 | struct mptsas_portinfo buffer, *port_info; | ||
| 3564 | u32 handle; | ||
| 3565 | int i; | ||
| 3566 | |||
| 3567 | handle = 0xFFFF; | ||
| 3568 | while (!mptsas_sas_expander_pg0(ioc, &buffer, | ||
| 3569 | (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << | ||
| 3570 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)) { | ||
| 3571 | |||
| 3572 | handle = buffer.phy_info[0].handle; | ||
| 3573 | port_info = mptsas_find_portinfo_by_sas_address(ioc, | ||
| 3574 | buffer.phy_info[0].identify.sas_address); | ||
| 3575 | |||
| 3576 | if (port_info) { | ||
| 3577 | /* refreshing handles */ | ||
| 3578 | for (i = 0; i < buffer.num_phys; i++) { | ||
| 3579 | port_info->phy_info[i].handle = handle; | ||
| 3580 | port_info->phy_info[i].identify.handle_parent = | ||
| 3581 | buffer.phy_info[0].identify.handle_parent; | ||
| 3582 | } | ||
| 3583 | mptsas_expander_refresh(ioc, port_info); | ||
| 3584 | kfree(buffer.phy_info); | ||
| 3585 | continue; | ||
| 3586 | } | ||
| 3587 | |||
| 3588 | port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL); | ||
| 3589 | if (!port_info) { | ||
| 3590 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 3591 | "%s: exit at line=%d\n", ioc->name, | ||
| 3592 | __func__, __LINE__)); | ||
| 3593 | return; | ||
| 3594 | } | ||
| 3595 | port_info->num_phys = buffer.num_phys; | ||
| 3596 | port_info->phy_info = buffer.phy_info; | ||
| 3597 | for (i = 0; i < port_info->num_phys; i++) | ||
| 3598 | port_info->phy_info[i].portinfo = port_info; | ||
| 3599 | mutex_lock(&ioc->sas_topology_mutex); | ||
| 3600 | list_add_tail(&port_info->list, &ioc->sas_topology); | ||
| 3601 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 3602 | printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, " | ||
| 3603 | "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys, | ||
| 3604 | (unsigned long long)buffer.phy_info[0].identify.sas_address); | ||
| 3605 | mptsas_expander_refresh(ioc, port_info); | ||
| 3606 | } | ||
| 2340 | } | 3607 | } |
| 2341 | 3608 | ||
| 2342 | /* | 3609 | static void |
| 2343 | * Start of day discovery | 3610 | mptsas_probe_devices(MPT_ADAPTER *ioc) |
| 2344 | */ | 3611 | { |
| 3612 | u16 handle; | ||
| 3613 | struct mptsas_devinfo sas_device; | ||
| 3614 | struct mptsas_phyinfo *phy_info; | ||
| 3615 | |||
| 3616 | handle = 0xFFFF; | ||
| 3617 | while (!(mptsas_sas_device_pg0(ioc, &sas_device, | ||
| 3618 | MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, handle))) { | ||
| 3619 | |||
| 3620 | handle = sas_device.handle; | ||
| 3621 | |||
| 3622 | if ((sas_device.device_info & | ||
| 3623 | (MPI_SAS_DEVICE_INFO_SSP_TARGET | | ||
| 3624 | MPI_SAS_DEVICE_INFO_STP_TARGET | | ||
| 3625 | MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) | ||
| 3626 | continue; | ||
| 3627 | |||
| 3628 | phy_info = mptsas_refreshing_device_handles(ioc, &sas_device); | ||
| 3629 | if (!phy_info) | ||
| 3630 | continue; | ||
| 3631 | |||
| 3632 | if (mptsas_get_rphy(phy_info)) | ||
| 3633 | continue; | ||
| 3634 | |||
| 3635 | mptsas_add_end_device(ioc, phy_info); | ||
| 3636 | } | ||
| 3637 | } | ||
| 3638 | |||
| 3639 | /** | ||
| 3640 | * mptsas_scan_sas_topology - | ||
| 3641 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 3642 | * @sas_address: | ||
| 3643 | * | ||
| 3644 | **/ | ||
| 2345 | static void | 3645 | static void |
| 2346 | mptsas_scan_sas_topology(MPT_ADAPTER *ioc) | 3646 | mptsas_scan_sas_topology(MPT_ADAPTER *ioc) |
| 2347 | { | 3647 | { |
| 2348 | u32 handle = 0xFFFF; | 3648 | struct scsi_device *sdev; |
| 2349 | int i; | 3649 | int i; |
| 2350 | 3650 | ||
| 2351 | mutex_lock(&ioc->sas_discovery_mutex); | ||
| 2352 | mptsas_probe_hba_phys(ioc); | 3651 | mptsas_probe_hba_phys(ioc); |
| 2353 | while (!mptsas_probe_expander_phys(ioc, &handle)) | 3652 | mptsas_probe_expanders(ioc); |
| 2354 | ; | 3653 | mptsas_probe_devices(ioc); |
| 3654 | |||
| 2355 | /* | 3655 | /* |
| 2356 | Reporting RAID volumes. | 3656 | Reporting RAID volumes. |
| 2357 | */ | 3657 | */ |
| 2358 | if (!ioc->ir_firmware) | 3658 | if (!ioc->ir_firmware || !ioc->raid_data.pIocPg2 || |
| 2359 | goto out; | 3659 | !ioc->raid_data.pIocPg2->NumActiveVolumes) |
| 2360 | if (!ioc->raid_data.pIocPg2) | 3660 | return; |
| 2361 | goto out; | ||
| 2362 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | ||
| 2363 | goto out; | ||
| 2364 | for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { | 3661 | for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { |
| 3662 | sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, | ||
| 3663 | ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); | ||
| 3664 | if (sdev) { | ||
| 3665 | scsi_device_put(sdev); | ||
| 3666 | continue; | ||
| 3667 | } | ||
| 3668 | printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, " | ||
| 3669 | "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, | ||
| 3670 | ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID); | ||
| 2365 | scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, | 3671 | scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, |
| 2366 | ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); | 3672 | ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); |
| 2367 | } | 3673 | } |
| 2368 | out: | ||
| 2369 | mutex_unlock(&ioc->sas_discovery_mutex); | ||
| 2370 | } | 3674 | } |
| 2371 | 3675 | ||
| 2372 | /* | 3676 | |
| 2373 | * Work queue thread to handle Runtime discovery | ||
| 2374 | * Mere purpose is the hot add/delete of expanders | ||
| 2375 | *(Mutex UNLOCKED) | ||
| 2376 | */ | ||
| 2377 | static void | 3677 | static void |
| 2378 | __mptsas_discovery_work(MPT_ADAPTER *ioc) | 3678 | mptsas_handle_queue_full_event(struct fw_event_work *fw_event) |
| 2379 | { | 3679 | { |
| 2380 | u32 handle = 0xFFFF; | 3680 | MPT_ADAPTER *ioc; |
| 3681 | EventDataQueueFull_t *qfull_data; | ||
| 3682 | struct mptsas_device_info *sas_info; | ||
| 3683 | struct scsi_device *sdev; | ||
| 3684 | int depth; | ||
| 3685 | int id = -1; | ||
| 3686 | int channel = -1; | ||
| 3687 | int fw_id, fw_channel; | ||
| 3688 | u16 current_depth; | ||
| 3689 | |||
| 3690 | |||
| 3691 | ioc = fw_event->ioc; | ||
| 3692 | qfull_data = (EventDataQueueFull_t *)fw_event->event_data; | ||
| 3693 | fw_id = qfull_data->TargetID; | ||
| 3694 | fw_channel = qfull_data->Bus; | ||
| 3695 | current_depth = le16_to_cpu(qfull_data->CurrentDepth); | ||
| 3696 | |||
| 3697 | /* if hidden raid component, look for the volume id */ | ||
| 3698 | mutex_lock(&ioc->sas_device_info_mutex); | ||
| 3699 | if (mptscsih_is_phys_disk(ioc, fw_channel, fw_id)) { | ||
| 3700 | list_for_each_entry(sas_info, &ioc->sas_device_info_list, | ||
| 3701 | list) { | ||
| 3702 | if (sas_info->is_cached || | ||
| 3703 | sas_info->is_logical_volume) | ||
| 3704 | continue; | ||
| 3705 | if (sas_info->is_hidden_raid_component && | ||
| 3706 | (sas_info->fw.channel == fw_channel && | ||
| 3707 | sas_info->fw.id == fw_id)) { | ||
| 3708 | id = sas_info->volume_id; | ||
| 3709 | channel = MPTSAS_RAID_CHANNEL; | ||
| 3710 | goto out; | ||
| 3711 | } | ||
| 3712 | } | ||
| 3713 | } else { | ||
| 3714 | list_for_each_entry(sas_info, &ioc->sas_device_info_list, | ||
| 3715 | list) { | ||
| 3716 | if (sas_info->is_cached || | ||
| 3717 | sas_info->is_hidden_raid_component || | ||
| 3718 | sas_info->is_logical_volume) | ||
| 3719 | continue; | ||
| 3720 | if (sas_info->fw.channel == fw_channel && | ||
| 3721 | sas_info->fw.id == fw_id) { | ||
| 3722 | id = sas_info->os.id; | ||
| 3723 | channel = sas_info->os.channel; | ||
| 3724 | goto out; | ||
| 3725 | } | ||
| 3726 | } | ||
| 2381 | 3727 | ||
| 2382 | ioc->sas_discovery_runtime=1; | 3728 | } |
| 2383 | mptsas_delete_expander_phys(ioc); | ||
| 2384 | mptsas_probe_hba_phys(ioc); | ||
| 2385 | while (!mptsas_probe_expander_phys(ioc, &handle)) | ||
| 2386 | ; | ||
| 2387 | ioc->sas_discovery_runtime=0; | ||
| 2388 | } | ||
| 2389 | 3729 | ||
| 2390 | /* | 3730 | out: |
| 2391 | * Work queue thread to handle Runtime discovery | 3731 | mutex_unlock(&ioc->sas_device_info_mutex); |
| 2392 | * Mere purpose is the hot add/delete of expanders | 3732 | |
| 2393 | *(Mutex LOCKED) | 3733 | if (id != -1) { |
| 2394 | */ | 3734 | shost_for_each_device(sdev, ioc->sh) { |
| 2395 | static void | 3735 | if (sdev->id == id && sdev->channel == channel) { |
| 2396 | mptsas_discovery_work(struct work_struct *work) | 3736 | if (current_depth > sdev->queue_depth) { |
| 2397 | { | 3737 | sdev_printk(KERN_INFO, sdev, |
| 2398 | struct mptsas_discovery_event *ev = | 3738 | "strange observation, the queue " |
| 2399 | container_of(work, struct mptsas_discovery_event, work); | 3739 | "depth is (%d) meanwhile fw queue " |
| 2400 | MPT_ADAPTER *ioc = ev->ioc; | 3740 | "depth (%d)\n", sdev->queue_depth, |
| 3741 | current_depth); | ||
| 3742 | continue; | ||
| 3743 | } | ||
| 3744 | depth = scsi_track_queue_full(sdev, | ||
| 3745 | current_depth - 1); | ||
| 3746 | if (depth > 0) | ||
| 3747 | sdev_printk(KERN_INFO, sdev, | ||
| 3748 | "Queue depth reduced to (%d)\n", | ||
| 3749 | depth); | ||
| 3750 | else if (depth < 0) | ||
| 3751 | sdev_printk(KERN_INFO, sdev, | ||
| 3752 | "Tagged Command Queueing is being " | ||
| 3753 | "disabled\n"); | ||
| 3754 | else if (depth == 0) | ||
| 3755 | sdev_printk(KERN_INFO, sdev, | ||
| 3756 | "Queue depth not changed yet\n"); | ||
| 3757 | } | ||
| 3758 | } | ||
| 3759 | } | ||
| 2401 | 3760 | ||
| 2402 | mutex_lock(&ioc->sas_discovery_mutex); | 3761 | mptsas_free_fw_event(ioc, fw_event); |
| 2403 | __mptsas_discovery_work(ioc); | ||
| 2404 | mutex_unlock(&ioc->sas_discovery_mutex); | ||
| 2405 | kfree(ev); | ||
| 2406 | } | 3762 | } |
| 2407 | 3763 | ||
| 3764 | |||
| 2408 | static struct mptsas_phyinfo * | 3765 | static struct mptsas_phyinfo * |
| 2409 | mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) | 3766 | mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) |
| 2410 | { | 3767 | { |
| @@ -2429,69 +3786,80 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) | |||
| 2429 | return phy_info; | 3786 | return phy_info; |
| 2430 | } | 3787 | } |
| 2431 | 3788 | ||
| 3789 | /** | ||
| 3790 | * mptsas_find_phyinfo_by_phys_disk_num - | ||
| 3791 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 3792 | * @phys_disk_num: | ||
| 3793 | * @channel: | ||
| 3794 | * @id: | ||
| 3795 | * | ||
| 3796 | **/ | ||
| 2432 | static struct mptsas_phyinfo * | 3797 | static struct mptsas_phyinfo * |
| 2433 | mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id) | 3798 | mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num, |
| 3799 | u8 channel, u8 id) | ||
| 2434 | { | 3800 | { |
| 2435 | struct mptsas_portinfo *port_info; | ||
| 2436 | struct mptsas_phyinfo *phy_info = NULL; | 3801 | struct mptsas_phyinfo *phy_info = NULL; |
| 3802 | struct mptsas_portinfo *port_info; | ||
| 3803 | RaidPhysDiskPage1_t *phys_disk = NULL; | ||
| 3804 | int num_paths; | ||
| 3805 | u64 sas_address = 0; | ||
| 2437 | int i; | 3806 | int i; |
| 2438 | 3807 | ||
| 2439 | mutex_lock(&ioc->sas_topology_mutex); | 3808 | phy_info = NULL; |
| 2440 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | 3809 | if (!ioc->raid_data.pIocPg3) |
| 2441 | for (i = 0; i < port_info->num_phys; i++) { | 3810 | return NULL; |
| 2442 | if (!mptsas_is_end_device( | 3811 | /* dual port support */ |
| 2443 | &port_info->phy_info[i].attached)) | 3812 | num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num); |
| 2444 | continue; | 3813 | if (!num_paths) |
| 2445 | if (port_info->phy_info[i].attached.id != id) | 3814 | goto out; |
| 2446 | continue; | 3815 | phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + |
| 2447 | if (port_info->phy_info[i].attached.channel != channel) | 3816 | (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); |
| 2448 | continue; | 3817 | if (!phys_disk) |
| 2449 | phy_info = &port_info->phy_info[i]; | 3818 | goto out; |
| 2450 | break; | 3819 | mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk); |
| 3820 | for (i = 0; i < num_paths; i++) { | ||
| 3821 | if ((phys_disk->Path[i].Flags & 1) != 0) | ||
| 3822 | /* entry no longer valid */ | ||
| 3823 | continue; | ||
| 3824 | if ((id == phys_disk->Path[i].PhysDiskID) && | ||
| 3825 | (channel == phys_disk->Path[i].PhysDiskBus)) { | ||
| 3826 | memcpy(&sas_address, &phys_disk->Path[i].WWID, | ||
| 3827 | sizeof(u64)); | ||
| 3828 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, | ||
| 3829 | sas_address); | ||
| 3830 | goto out; | ||
| 2451 | } | 3831 | } |
| 2452 | } | 3832 | } |
| 2453 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 2454 | return phy_info; | ||
| 2455 | } | ||
| 2456 | 3833 | ||
| 2457 | static struct mptsas_phyinfo * | 3834 | out: |
| 2458 | mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | 3835 | kfree(phys_disk); |
| 2459 | { | 3836 | if (phy_info) |
| 2460 | struct mptsas_portinfo *port_info; | 3837 | return phy_info; |
| 2461 | struct mptsas_phyinfo *phy_info = NULL; | ||
| 2462 | int i; | ||
| 2463 | 3838 | ||
| 3839 | /* | ||
| 3840 | * Extra code to handle RAID0 case, where the sas_address is not updated | ||
| 3841 | * in phys_disk_page_1 when hotswapped | ||
| 3842 | */ | ||
| 2464 | mutex_lock(&ioc->sas_topology_mutex); | 3843 | mutex_lock(&ioc->sas_topology_mutex); |
| 2465 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | 3844 | list_for_each_entry(port_info, &ioc->sas_topology, list) { |
| 2466 | for (i = 0; i < port_info->num_phys; i++) { | 3845 | for (i = 0; i < port_info->num_phys && !phy_info; i++) { |
| 2467 | if (!mptsas_is_end_device( | 3846 | if (!mptsas_is_end_device( |
| 2468 | &port_info->phy_info[i].attached)) | 3847 | &port_info->phy_info[i].attached)) |
| 2469 | continue; | 3848 | continue; |
| 2470 | if (port_info->phy_info[i].attached.phys_disk_num == ~0) | 3849 | if (port_info->phy_info[i].attached.phys_disk_num == ~0) |
| 2471 | continue; | 3850 | continue; |
| 2472 | if (port_info->phy_info[i].attached.phys_disk_num != id) | 3851 | if ((port_info->phy_info[i].attached.phys_disk_num == |
| 2473 | continue; | 3852 | phys_disk_num) && |
| 2474 | if (port_info->phy_info[i].attached.channel != channel) | 3853 | (port_info->phy_info[i].attached.id == id) && |
| 2475 | continue; | 3854 | (port_info->phy_info[i].attached.channel == |
| 2476 | phy_info = &port_info->phy_info[i]; | 3855 | channel)) |
| 2477 | break; | 3856 | phy_info = &port_info->phy_info[i]; |
| 2478 | } | 3857 | } |
| 2479 | } | 3858 | } |
| 2480 | mutex_unlock(&ioc->sas_topology_mutex); | 3859 | mutex_unlock(&ioc->sas_topology_mutex); |
| 2481 | return phy_info; | 3860 | return phy_info; |
| 2482 | } | 3861 | } |
| 2483 | 3862 | ||
| 2484 | /* | ||
| 2485 | * Work queue thread to clear the persitency table | ||
| 2486 | */ | ||
| 2487 | static void | ||
| 2488 | mptsas_persist_clear_table(struct work_struct *work) | ||
| 2489 | { | ||
| 2490 | MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task); | ||
| 2491 | |||
| 2492 | mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); | ||
| 2493 | } | ||
| 2494 | |||
| 2495 | static void | 3863 | static void |
| 2496 | mptsas_reprobe_lun(struct scsi_device *sdev, void *data) | 3864 | mptsas_reprobe_lun(struct scsi_device *sdev, void *data) |
| 2497 | { | 3865 | { |
| @@ -2517,7 +3885,8 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 2517 | pRaidVolumePage0_t buffer = NULL; | 3885 | pRaidVolumePage0_t buffer = NULL; |
| 2518 | RaidPhysDiskPage0_t phys_disk; | 3886 | RaidPhysDiskPage0_t phys_disk; |
| 2519 | int i; | 3887 | int i; |
| 2520 | struct mptsas_hotplug_event *ev; | 3888 | struct mptsas_phyinfo *phy_info; |
| 3889 | struct mptsas_devinfo sas_device; | ||
| 2521 | 3890 | ||
| 2522 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | 3891 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); |
| 2523 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | 3892 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); |
| @@ -2557,20 +3926,16 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 2557 | buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) | 3926 | buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) |
| 2558 | continue; | 3927 | continue; |
| 2559 | 3928 | ||
| 2560 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | 3929 | if (mptsas_sas_device_pg0(ioc, &sas_device, |
| 2561 | if (!ev) { | 3930 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << |
| 2562 | printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name); | 3931 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), |
| 2563 | goto out; | 3932 | (phys_disk.PhysDiskBus << 8) + |
| 2564 | } | 3933 | phys_disk.PhysDiskID)) |
| 3934 | continue; | ||
| 2565 | 3935 | ||
| 2566 | INIT_WORK(&ev->work, mptsas_hotplug_work); | 3936 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, |
| 2567 | ev->ioc = ioc; | 3937 | sas_device.sas_address); |
| 2568 | ev->id = phys_disk.PhysDiskID; | 3938 | mptsas_add_end_device(ioc, phy_info); |
| 2569 | ev->channel = phys_disk.PhysDiskBus; | ||
| 2570 | ev->phys_disk_num_valid = 1; | ||
| 2571 | ev->phys_disk_num = phys_disk.PhysDiskNum; | ||
| 2572 | ev->event_type = MPTSAS_ADD_DEVICE; | ||
| 2573 | schedule_work(&ev->work); | ||
| 2574 | } | 3939 | } |
| 2575 | 3940 | ||
| 2576 | out: | 3941 | out: |
| @@ -2582,417 +3947,386 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 2582 | * Work queue thread to handle SAS hotplug events | 3947 | * Work queue thread to handle SAS hotplug events |
| 2583 | */ | 3948 | */ |
| 2584 | static void | 3949 | static void |
| 2585 | mptsas_hotplug_work(struct work_struct *work) | 3950 | mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, |
| 3951 | struct mptsas_hotplug_event *hot_plug_info) | ||
| 2586 | { | 3952 | { |
| 2587 | struct mptsas_hotplug_event *ev = | ||
| 2588 | container_of(work, struct mptsas_hotplug_event, work); | ||
| 2589 | |||
| 2590 | MPT_ADAPTER *ioc = ev->ioc; | ||
| 2591 | struct mptsas_phyinfo *phy_info; | 3953 | struct mptsas_phyinfo *phy_info; |
| 2592 | struct sas_rphy *rphy; | ||
| 2593 | struct sas_port *port; | ||
| 2594 | struct scsi_device *sdev; | ||
| 2595 | struct scsi_target * starget; | 3954 | struct scsi_target * starget; |
| 2596 | struct sas_identify identify; | ||
| 2597 | char *ds = NULL; | ||
| 2598 | struct mptsas_devinfo sas_device; | 3955 | struct mptsas_devinfo sas_device; |
| 2599 | VirtTarget *vtarget; | 3956 | VirtTarget *vtarget; |
| 2600 | VirtDevice *vdevice; | 3957 | int i; |
| 2601 | 3958 | ||
| 2602 | mutex_lock(&ioc->sas_discovery_mutex); | 3959 | switch (hot_plug_info->event_type) { |
| 2603 | switch (ev->event_type) { | ||
| 2604 | case MPTSAS_DEL_DEVICE: | ||
| 2605 | 3960 | ||
| 2606 | phy_info = NULL; | 3961 | case MPTSAS_ADD_PHYSDISK: |
| 2607 | if (ev->phys_disk_num_valid) { | 3962 | |
| 2608 | if (ev->hidden_raid_component){ | 3963 | if (!ioc->raid_data.pIocPg2) |
| 2609 | if (mptsas_sas_device_pg0(ioc, &sas_device, | 3964 | break; |
| 2610 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | 3965 | |
| 2611 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | 3966 | for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { |
| 2612 | (ev->channel << 8) + ev->id)) { | 3967 | if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == |
| 2613 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 3968 | hot_plug_info->id) { |
| 2614 | "%s: exit at line=%d\n", ioc->name, | 3969 | printk(MYIOC_s_WARN_FMT "firmware bug: unable " |
| 2615 | __func__, __LINE__)); | 3970 | "to add hidden disk - target_id matchs " |
| 2616 | break; | 3971 | "volume_id\n", ioc->name); |
| 2617 | } | 3972 | mptsas_free_fw_event(ioc, fw_event); |
| 2618 | phy_info = mptsas_find_phyinfo_by_sas_address( | 3973 | return; |
| 2619 | ioc, sas_device.sas_address); | 3974 | } |
| 2620 | }else | ||
| 2621 | phy_info = mptsas_find_phyinfo_by_phys_disk_num( | ||
| 2622 | ioc, ev->channel, ev->phys_disk_num); | ||
| 2623 | } | 3975 | } |
| 3976 | mpt_findImVolumes(ioc); | ||
| 2624 | 3977 | ||
| 3978 | case MPTSAS_ADD_DEVICE: | ||
| 3979 | memset(&sas_device, 0, sizeof(struct mptsas_devinfo)); | ||
| 3980 | mptsas_sas_device_pg0(ioc, &sas_device, | ||
| 3981 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | ||
| 3982 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||
| 3983 | (hot_plug_info->channel << 8) + | ||
| 3984 | hot_plug_info->id); | ||
| 3985 | |||
| 3986 | if (!sas_device.handle) | ||
| 3987 | return; | ||
| 3988 | |||
| 3989 | phy_info = mptsas_refreshing_device_handles(ioc, &sas_device); | ||
| 2625 | if (!phy_info) | 3990 | if (!phy_info) |
| 2626 | phy_info = mptsas_find_phyinfo_by_target(ioc, | 3991 | break; |
| 2627 | ev->channel, ev->id); | ||
| 2628 | 3992 | ||
| 2629 | /* | 3993 | if (mptsas_get_rphy(phy_info)) |
| 2630 | * Sanity checks, for non-existing phys and remote rphys. | 3994 | break; |
| 2631 | */ | 3995 | |
| 2632 | if (!phy_info){ | 3996 | mptsas_add_end_device(ioc, phy_info); |
| 3997 | break; | ||
| 3998 | |||
| 3999 | case MPTSAS_DEL_DEVICE: | ||
| 4000 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, | ||
| 4001 | hot_plug_info->sas_address); | ||
| 4002 | mptsas_del_end_device(ioc, phy_info); | ||
| 4003 | break; | ||
| 4004 | |||
| 4005 | case MPTSAS_DEL_PHYSDISK: | ||
| 4006 | |||
| 4007 | mpt_findImVolumes(ioc); | ||
| 4008 | |||
| 4009 | phy_info = mptsas_find_phyinfo_by_phys_disk_num( | ||
| 4010 | ioc, hot_plug_info->phys_disk_num, | ||
| 4011 | hot_plug_info->channel, | ||
| 4012 | hot_plug_info->id); | ||
| 4013 | mptsas_del_end_device(ioc, phy_info); | ||
| 4014 | break; | ||
| 4015 | |||
| 4016 | case MPTSAS_ADD_PHYSDISK_REPROBE: | ||
| 4017 | |||
| 4018 | if (mptsas_sas_device_pg0(ioc, &sas_device, | ||
| 4019 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | ||
| 4020 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||
| 4021 | (hot_plug_info->channel << 8) + hot_plug_info->id)) { | ||
| 2633 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 4022 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 2634 | "%s: exit at line=%d\n", ioc->name, | 4023 | "%s: fw_id=%d exit at line=%d\n", ioc->name, |
| 2635 | __func__, __LINE__)); | 4024 | __func__, hot_plug_info->id, __LINE__)); |
| 2636 | break; | 4025 | break; |
| 2637 | } | 4026 | } |
| 2638 | if (!phy_info->port_details) { | 4027 | |
| 4028 | phy_info = mptsas_find_phyinfo_by_sas_address( | ||
| 4029 | ioc, sas_device.sas_address); | ||
| 4030 | |||
| 4031 | if (!phy_info) { | ||
| 2639 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 4032 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 2640 | "%s: exit at line=%d\n", ioc->name, | 4033 | "%s: fw_id=%d exit at line=%d\n", ioc->name, |
| 2641 | __func__, __LINE__)); | 4034 | __func__, hot_plug_info->id, __LINE__)); |
| 2642 | break; | 4035 | break; |
| 2643 | } | 4036 | } |
| 2644 | rphy = mptsas_get_rphy(phy_info); | 4037 | |
| 2645 | if (!rphy) { | 4038 | starget = mptsas_get_starget(phy_info); |
| 4039 | if (!starget) { | ||
| 2646 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 4040 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 2647 | "%s: exit at line=%d\n", ioc->name, | 4041 | "%s: fw_id=%d exit at line=%d\n", ioc->name, |
| 2648 | __func__, __LINE__)); | 4042 | __func__, hot_plug_info->id, __LINE__)); |
| 2649 | break; | 4043 | break; |
| 2650 | } | 4044 | } |
| 2651 | 4045 | ||
| 2652 | port = mptsas_get_port(phy_info); | 4046 | vtarget = starget->hostdata; |
| 2653 | if (!port) { | 4047 | if (!vtarget) { |
| 2654 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 4048 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 2655 | "%s: exit at line=%d\n", ioc->name, | 4049 | "%s: fw_id=%d exit at line=%d\n", ioc->name, |
| 2656 | __func__, __LINE__)); | 4050 | __func__, hot_plug_info->id, __LINE__)); |
| 2657 | break; | 4051 | break; |
| 2658 | } | 4052 | } |
| 2659 | 4053 | ||
| 2660 | starget = mptsas_get_starget(phy_info); | 4054 | mpt_findImVolumes(ioc); |
| 2661 | if (starget) { | ||
| 2662 | vtarget = starget->hostdata; | ||
| 2663 | 4055 | ||
| 2664 | if (!vtarget) { | 4056 | starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Hidding: " |
| 2665 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 4057 | "fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n", |
| 2666 | "%s: exit at line=%d\n", ioc->name, | 4058 | ioc->name, hot_plug_info->channel, hot_plug_info->id, |
| 2667 | __func__, __LINE__)); | 4059 | hot_plug_info->phys_disk_num, (unsigned long long) |
| 2668 | break; | 4060 | sas_device.sas_address); |
| 2669 | } | ||
| 2670 | 4061 | ||
| 2671 | /* | 4062 | vtarget->id = hot_plug_info->phys_disk_num; |
| 2672 | * Handling RAID components | 4063 | vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; |
| 2673 | */ | 4064 | phy_info->attached.phys_disk_num = hot_plug_info->phys_disk_num; |
| 2674 | if (ev->phys_disk_num_valid && | 4065 | mptsas_reprobe_target(starget, 1); |
| 2675 | ev->hidden_raid_component) { | ||
| 2676 | printk(MYIOC_s_INFO_FMT | ||
| 2677 | "RAID Hidding: channel=%d, id=%d, " | ||
| 2678 | "physdsk %d \n", ioc->name, ev->channel, | ||
| 2679 | ev->id, ev->phys_disk_num); | ||
| 2680 | vtarget->id = ev->phys_disk_num; | ||
| 2681 | vtarget->tflags |= | ||
| 2682 | MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
| 2683 | mptsas_reprobe_target(starget, 1); | ||
| 2684 | phy_info->attached.phys_disk_num = | ||
| 2685 | ev->phys_disk_num; | ||
| 2686 | break; | ||
| 2687 | } | ||
| 2688 | } | ||
| 2689 | |||
| 2690 | if (phy_info->attached.device_info & | ||
| 2691 | MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||
| 2692 | ds = "ssp"; | ||
| 2693 | if (phy_info->attached.device_info & | ||
| 2694 | MPI_SAS_DEVICE_INFO_STP_TARGET) | ||
| 2695 | ds = "stp"; | ||
| 2696 | if (phy_info->attached.device_info & | ||
| 2697 | MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||
| 2698 | ds = "sata"; | ||
| 2699 | |||
| 2700 | printk(MYIOC_s_INFO_FMT | ||
| 2701 | "removing %s device, channel %d, id %d, phy %d\n", | ||
| 2702 | ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); | ||
| 2703 | dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT | ||
| 2704 | "delete port (%d)\n", ioc->name, port->port_identifier); | ||
| 2705 | sas_port_delete(port); | ||
| 2706 | mptsas_port_delete(ioc, phy_info->port_details); | ||
| 2707 | break; | 4066 | break; |
| 2708 | case MPTSAS_ADD_DEVICE: | ||
| 2709 | 4067 | ||
| 2710 | if (ev->phys_disk_num_valid) | 4068 | case MPTSAS_DEL_PHYSDISK_REPROBE: |
| 2711 | mpt_findImVolumes(ioc); | ||
| 2712 | 4069 | ||
| 2713 | /* | ||
| 2714 | * Refresh sas device pg0 data | ||
| 2715 | */ | ||
| 2716 | if (mptsas_sas_device_pg0(ioc, &sas_device, | 4070 | if (mptsas_sas_device_pg0(ioc, &sas_device, |
| 2717 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | 4071 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << |
| 2718 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | 4072 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), |
| 2719 | (ev->channel << 8) + ev->id)) { | 4073 | (hot_plug_info->channel << 8) + hot_plug_info->id)) { |
| 2720 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 4074 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 2721 | "%s: exit at line=%d\n", ioc->name, | 4075 | "%s: fw_id=%d exit at line=%d\n", |
| 2722 | __func__, __LINE__)); | 4076 | ioc->name, __func__, |
| 4077 | hot_plug_info->id, __LINE__)); | ||
| 2723 | break; | 4078 | break; |
| 2724 | } | 4079 | } |
| 2725 | 4080 | ||
| 2726 | __mptsas_discovery_work(ioc); | ||
| 2727 | |||
| 2728 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, | 4081 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, |
| 2729 | sas_device.sas_address); | 4082 | sas_device.sas_address); |
| 2730 | 4083 | if (!phy_info) { | |
| 2731 | if (!phy_info || !phy_info->port_details) { | ||
| 2732 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 4084 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 2733 | "%s: exit at line=%d\n", ioc->name, | 4085 | "%s: fw_id=%d exit at line=%d\n", ioc->name, |
| 2734 | __func__, __LINE__)); | 4086 | __func__, hot_plug_info->id, __LINE__)); |
| 2735 | break; | 4087 | break; |
| 2736 | } | 4088 | } |
| 2737 | 4089 | ||
| 2738 | starget = mptsas_get_starget(phy_info); | 4090 | starget = mptsas_get_starget(phy_info); |
| 2739 | if (starget && (!ev->hidden_raid_component)){ | 4091 | if (!starget) { |
| 2740 | 4092 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | |
| 2741 | vtarget = starget->hostdata; | 4093 | "%s: fw_id=%d exit at line=%d\n", ioc->name, |
| 2742 | 4094 | __func__, hot_plug_info->id, __LINE__)); | |
| 2743 | if (!vtarget) { | ||
| 2744 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 2745 | "%s: exit at line=%d\n", ioc->name, | ||
| 2746 | __func__, __LINE__)); | ||
| 2747 | break; | ||
| 2748 | } | ||
| 2749 | /* | ||
| 2750 | * Handling RAID components | ||
| 2751 | */ | ||
| 2752 | if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { | ||
| 2753 | printk(MYIOC_s_INFO_FMT | ||
| 2754 | "RAID Exposing: channel=%d, id=%d, " | ||
| 2755 | "physdsk %d \n", ioc->name, ev->channel, | ||
| 2756 | ev->id, ev->phys_disk_num); | ||
| 2757 | vtarget->tflags &= | ||
| 2758 | ~MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
| 2759 | vtarget->id = ev->id; | ||
| 2760 | mptsas_reprobe_target(starget, 0); | ||
| 2761 | phy_info->attached.phys_disk_num = ~0; | ||
| 2762 | } | ||
| 2763 | break; | 4095 | break; |
| 2764 | } | 4096 | } |
| 2765 | 4097 | ||
| 2766 | if (mptsas_get_rphy(phy_info)) { | 4098 | vtarget = starget->hostdata; |
| 4099 | if (!vtarget) { | ||
| 2767 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 4100 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 2768 | "%s: exit at line=%d\n", ioc->name, | 4101 | "%s: fw_id=%d exit at line=%d\n", ioc->name, |
| 2769 | __func__, __LINE__)); | 4102 | __func__, hot_plug_info->id, __LINE__)); |
| 2770 | if (ev->channel) printk("%d\n", __LINE__); | ||
| 2771 | break; | 4103 | break; |
| 2772 | } | 4104 | } |
| 2773 | 4105 | ||
| 2774 | port = mptsas_get_port(phy_info); | 4106 | if (!(vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) { |
| 2775 | if (!port) { | ||
| 2776 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 4107 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 2777 | "%s: exit at line=%d\n", ioc->name, | 4108 | "%s: fw_id=%d exit at line=%d\n", ioc->name, |
| 2778 | __func__, __LINE__)); | 4109 | __func__, hot_plug_info->id, __LINE__)); |
| 2779 | break; | 4110 | break; |
| 2780 | } | 4111 | } |
| 2781 | memcpy(&phy_info->attached, &sas_device, | ||
| 2782 | sizeof(struct mptsas_devinfo)); | ||
| 2783 | |||
| 2784 | if (phy_info->attached.device_info & | ||
| 2785 | MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||
| 2786 | ds = "ssp"; | ||
| 2787 | if (phy_info->attached.device_info & | ||
| 2788 | MPI_SAS_DEVICE_INFO_STP_TARGET) | ||
| 2789 | ds = "stp"; | ||
| 2790 | if (phy_info->attached.device_info & | ||
| 2791 | MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||
| 2792 | ds = "sata"; | ||
| 2793 | |||
| 2794 | printk(MYIOC_s_INFO_FMT | ||
| 2795 | "attaching %s device, channel %d, id %d, phy %d\n", | ||
| 2796 | ioc->name, ds, ev->channel, ev->id, ev->phy_id); | ||
| 2797 | 4112 | ||
| 2798 | mptsas_parse_device_info(&identify, &phy_info->attached); | 4113 | mpt_findImVolumes(ioc); |
| 2799 | rphy = sas_end_device_alloc(port); | ||
| 2800 | if (!rphy) { | ||
| 2801 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 2802 | "%s: exit at line=%d\n", ioc->name, | ||
| 2803 | __func__, __LINE__)); | ||
| 2804 | break; /* non-fatal: an rphy can be added later */ | ||
| 2805 | } | ||
| 2806 | 4114 | ||
| 2807 | rphy->identify = identify; | 4115 | starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Exposing:" |
| 2808 | if (sas_rphy_add(rphy)) { | 4116 | " fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n", |
| 2809 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 4117 | ioc->name, hot_plug_info->channel, hot_plug_info->id, |
| 2810 | "%s: exit at line=%d\n", ioc->name, | 4118 | hot_plug_info->phys_disk_num, (unsigned long long) |
| 2811 | __func__, __LINE__)); | 4119 | sas_device.sas_address); |
| 2812 | sas_rphy_free(rphy); | 4120 | |
| 2813 | break; | 4121 | vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; |
| 2814 | } | 4122 | vtarget->id = hot_plug_info->id; |
| 2815 | mptsas_set_rphy(ioc, phy_info, rphy); | 4123 | phy_info->attached.phys_disk_num = ~0; |
| 4124 | mptsas_reprobe_target(starget, 0); | ||
| 4125 | mptsas_add_device_component_by_fw(ioc, | ||
| 4126 | hot_plug_info->channel, hot_plug_info->id); | ||
| 2816 | break; | 4127 | break; |
| 4128 | |||
| 2817 | case MPTSAS_ADD_RAID: | 4129 | case MPTSAS_ADD_RAID: |
| 2818 | sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, | 4130 | |
| 2819 | ev->id, 0); | ||
| 2820 | if (sdev) { | ||
| 2821 | scsi_device_put(sdev); | ||
| 2822 | break; | ||
| 2823 | } | ||
| 2824 | printk(MYIOC_s_INFO_FMT | ||
| 2825 | "attaching raid volume, channel %d, id %d\n", | ||
| 2826 | ioc->name, MPTSAS_RAID_CHANNEL, ev->id); | ||
| 2827 | scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0); | ||
| 2828 | mpt_findImVolumes(ioc); | 4131 | mpt_findImVolumes(ioc); |
| 4132 | printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, " | ||
| 4133 | "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, | ||
| 4134 | hot_plug_info->id); | ||
| 4135 | scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, | ||
| 4136 | hot_plug_info->id, 0); | ||
| 2829 | break; | 4137 | break; |
| 4138 | |||
| 2830 | case MPTSAS_DEL_RAID: | 4139 | case MPTSAS_DEL_RAID: |
| 2831 | sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, | 4140 | |
| 2832 | ev->id, 0); | ||
| 2833 | if (!sdev) | ||
| 2834 | break; | ||
| 2835 | printk(MYIOC_s_INFO_FMT | ||
| 2836 | "removing raid volume, channel %d, id %d\n", | ||
| 2837 | ioc->name, MPTSAS_RAID_CHANNEL, ev->id); | ||
| 2838 | vdevice = sdev->hostdata; | ||
| 2839 | scsi_remove_device(sdev); | ||
| 2840 | scsi_device_put(sdev); | ||
| 2841 | mpt_findImVolumes(ioc); | 4141 | mpt_findImVolumes(ioc); |
| 4142 | printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, " | ||
| 4143 | "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, | ||
| 4144 | hot_plug_info->id); | ||
| 4145 | scsi_remove_device(hot_plug_info->sdev); | ||
| 4146 | scsi_device_put(hot_plug_info->sdev); | ||
| 2842 | break; | 4147 | break; |
| 4148 | |||
| 2843 | case MPTSAS_ADD_INACTIVE_VOLUME: | 4149 | case MPTSAS_ADD_INACTIVE_VOLUME: |
| 4150 | |||
| 4151 | mpt_findImVolumes(ioc); | ||
| 2844 | mptsas_adding_inactive_raid_components(ioc, | 4152 | mptsas_adding_inactive_raid_components(ioc, |
| 2845 | ev->channel, ev->id); | 4153 | hot_plug_info->channel, hot_plug_info->id); |
| 2846 | break; | 4154 | break; |
| 2847 | case MPTSAS_IGNORE_EVENT: | 4155 | |
| 2848 | default: | 4156 | default: |
| 2849 | break; | 4157 | break; |
| 2850 | } | 4158 | } |
| 2851 | 4159 | ||
| 2852 | mutex_unlock(&ioc->sas_discovery_mutex); | 4160 | mptsas_free_fw_event(ioc, fw_event); |
| 2853 | kfree(ev); | ||
| 2854 | } | 4161 | } |
| 2855 | 4162 | ||
| 2856 | static void | 4163 | static void |
| 2857 | mptsas_send_sas_event(MPT_ADAPTER *ioc, | 4164 | mptsas_send_sas_event(struct fw_event_work *fw_event) |
| 2858 | EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data) | ||
| 2859 | { | 4165 | { |
| 2860 | struct mptsas_hotplug_event *ev; | 4166 | MPT_ADAPTER *ioc; |
| 2861 | u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo); | 4167 | struct mptsas_hotplug_event hot_plug_info; |
| 2862 | __le64 sas_address; | 4168 | EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data; |
| 4169 | u32 device_info; | ||
| 4170 | u64 sas_address; | ||
| 4171 | |||
| 4172 | ioc = fw_event->ioc; | ||
| 4173 | sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *) | ||
| 4174 | fw_event->event_data; | ||
| 4175 | device_info = le32_to_cpu(sas_event_data->DeviceInfo); | ||
| 2863 | 4176 | ||
| 2864 | if ((device_info & | 4177 | if ((device_info & |
| 2865 | (MPI_SAS_DEVICE_INFO_SSP_TARGET | | 4178 | (MPI_SAS_DEVICE_INFO_SSP_TARGET | |
| 2866 | MPI_SAS_DEVICE_INFO_STP_TARGET | | 4179 | MPI_SAS_DEVICE_INFO_STP_TARGET | |
| 2867 | MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) | 4180 | MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) { |
| 4181 | mptsas_free_fw_event(ioc, fw_event); | ||
| 4182 | return; | ||
| 4183 | } | ||
| 4184 | |||
| 4185 | if (sas_event_data->ReasonCode == | ||
| 4186 | MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED) { | ||
| 4187 | mptbase_sas_persist_operation(ioc, | ||
| 4188 | MPI_SAS_OP_CLEAR_NOT_PRESENT); | ||
| 4189 | mptsas_free_fw_event(ioc, fw_event); | ||
| 2868 | return; | 4190 | return; |
| 4191 | } | ||
| 2869 | 4192 | ||
| 2870 | switch (sas_event_data->ReasonCode) { | 4193 | switch (sas_event_data->ReasonCode) { |
| 2871 | case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: | 4194 | case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: |
| 2872 | |||
| 2873 | mptsas_target_reset_queue(ioc, sas_event_data); | ||
| 2874 | break; | ||
| 2875 | |||
| 2876 | case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: | 4195 | case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: |
| 2877 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | 4196 | memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event)); |
| 2878 | if (!ev) { | 4197 | hot_plug_info.handle = le16_to_cpu(sas_event_data->DevHandle); |
| 2879 | printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name); | 4198 | hot_plug_info.channel = sas_event_data->Bus; |
| 2880 | break; | 4199 | hot_plug_info.id = sas_event_data->TargetID; |
| 2881 | } | 4200 | hot_plug_info.phy_id = sas_event_data->PhyNum; |
| 2882 | |||
| 2883 | INIT_WORK(&ev->work, mptsas_hotplug_work); | ||
| 2884 | ev->ioc = ioc; | ||
| 2885 | ev->handle = le16_to_cpu(sas_event_data->DevHandle); | ||
| 2886 | ev->parent_handle = | ||
| 2887 | le16_to_cpu(sas_event_data->ParentDevHandle); | ||
| 2888 | ev->channel = sas_event_data->Bus; | ||
| 2889 | ev->id = sas_event_data->TargetID; | ||
| 2890 | ev->phy_id = sas_event_data->PhyNum; | ||
| 2891 | memcpy(&sas_address, &sas_event_data->SASAddress, | 4201 | memcpy(&sas_address, &sas_event_data->SASAddress, |
| 2892 | sizeof(__le64)); | 4202 | sizeof(u64)); |
| 2893 | ev->sas_address = le64_to_cpu(sas_address); | 4203 | hot_plug_info.sas_address = le64_to_cpu(sas_address); |
| 2894 | ev->device_info = device_info; | 4204 | hot_plug_info.device_info = device_info; |
| 2895 | |||
| 2896 | if (sas_event_data->ReasonCode & | 4205 | if (sas_event_data->ReasonCode & |
| 2897 | MPI_EVENT_SAS_DEV_STAT_RC_ADDED) | 4206 | MPI_EVENT_SAS_DEV_STAT_RC_ADDED) |
| 2898 | ev->event_type = MPTSAS_ADD_DEVICE; | 4207 | hot_plug_info.event_type = MPTSAS_ADD_DEVICE; |
| 2899 | else | 4208 | else |
| 2900 | ev->event_type = MPTSAS_DEL_DEVICE; | 4209 | hot_plug_info.event_type = MPTSAS_DEL_DEVICE; |
| 2901 | schedule_work(&ev->work); | 4210 | mptsas_hotplug_work(ioc, fw_event, &hot_plug_info); |
| 2902 | break; | 4211 | break; |
| 4212 | |||
| 2903 | case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: | 4213 | case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: |
| 2904 | /* | 4214 | mptbase_sas_persist_operation(ioc, |
| 2905 | * Persistent table is full. | 4215 | MPI_SAS_OP_CLEAR_NOT_PRESENT); |
| 2906 | */ | 4216 | mptsas_free_fw_event(ioc, fw_event); |
| 2907 | INIT_WORK(&ioc->sas_persist_task, | ||
| 2908 | mptsas_persist_clear_table); | ||
| 2909 | schedule_work(&ioc->sas_persist_task); | ||
| 2910 | break; | 4217 | break; |
| 2911 | /* | 4218 | |
| 2912 | * TODO, handle other events | ||
| 2913 | */ | ||
| 2914 | case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: | 4219 | case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: |
| 2915 | case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: | 4220 | /* TODO */ |
| 2916 | case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: | 4221 | case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: |
| 2917 | case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: | 4222 | /* TODO */ |
| 2918 | case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: | ||
| 2919 | case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: | ||
| 2920 | case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: | ||
| 2921 | default: | 4223 | default: |
| 4224 | mptsas_free_fw_event(ioc, fw_event); | ||
| 2922 | break; | 4225 | break; |
| 2923 | } | 4226 | } |
| 2924 | } | 4227 | } |
| 4228 | |||
| 2925 | static void | 4229 | static void |
| 2926 | mptsas_send_raid_event(MPT_ADAPTER *ioc, | 4230 | mptsas_send_raid_event(struct fw_event_work *fw_event) |
| 2927 | EVENT_DATA_RAID *raid_event_data) | ||
| 2928 | { | 4231 | { |
| 2929 | struct mptsas_hotplug_event *ev; | 4232 | MPT_ADAPTER *ioc; |
| 2930 | int status = le32_to_cpu(raid_event_data->SettingsStatus); | 4233 | EVENT_DATA_RAID *raid_event_data; |
| 2931 | int state = (status >> 8) & 0xff; | 4234 | struct mptsas_hotplug_event hot_plug_info; |
| 2932 | 4235 | int status; | |
| 2933 | if (ioc->bus_type != SAS) | 4236 | int state; |
| 2934 | return; | 4237 | struct scsi_device *sdev = NULL; |
| 2935 | 4238 | VirtDevice *vdevice = NULL; | |
| 2936 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | 4239 | RaidPhysDiskPage0_t phys_disk; |
| 2937 | if (!ev) { | 4240 | |
| 2938 | printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name); | 4241 | ioc = fw_event->ioc; |
| 2939 | return; | 4242 | raid_event_data = (EVENT_DATA_RAID *)fw_event->event_data; |
| 4243 | status = le32_to_cpu(raid_event_data->SettingsStatus); | ||
| 4244 | state = (status >> 8) & 0xff; | ||
| 4245 | |||
| 4246 | memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event)); | ||
| 4247 | hot_plug_info.id = raid_event_data->VolumeID; | ||
| 4248 | hot_plug_info.channel = raid_event_data->VolumeBus; | ||
| 4249 | hot_plug_info.phys_disk_num = raid_event_data->PhysDiskNum; | ||
| 4250 | |||
| 4251 | if (raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_DELETED || | ||
| 4252 | raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_CREATED || | ||
| 4253 | raid_event_data->ReasonCode == | ||
| 4254 | MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED) { | ||
| 4255 | sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, | ||
| 4256 | hot_plug_info.id, 0); | ||
| 4257 | hot_plug_info.sdev = sdev; | ||
| 4258 | if (sdev) | ||
| 4259 | vdevice = sdev->hostdata; | ||
| 2940 | } | 4260 | } |
| 2941 | 4261 | ||
| 2942 | INIT_WORK(&ev->work, mptsas_hotplug_work); | 4262 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: " |
| 2943 | ev->ioc = ioc; | 4263 | "ReasonCode=%02x\n", ioc->name, __func__, |
| 2944 | ev->id = raid_event_data->VolumeID; | 4264 | raid_event_data->ReasonCode)); |
| 2945 | ev->channel = raid_event_data->VolumeBus; | ||
| 2946 | ev->event_type = MPTSAS_IGNORE_EVENT; | ||
| 2947 | 4265 | ||
| 2948 | switch (raid_event_data->ReasonCode) { | 4266 | switch (raid_event_data->ReasonCode) { |
| 2949 | case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: | 4267 | case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: |
| 2950 | ev->phys_disk_num_valid = 1; | 4268 | hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK_REPROBE; |
| 2951 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||
| 2952 | ev->event_type = MPTSAS_ADD_DEVICE; | ||
| 2953 | break; | 4269 | break; |
| 2954 | case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: | 4270 | case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: |
| 2955 | ev->phys_disk_num_valid = 1; | 4271 | hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK_REPROBE; |
| 2956 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||
| 2957 | ev->hidden_raid_component = 1; | ||
| 2958 | ev->event_type = MPTSAS_DEL_DEVICE; | ||
| 2959 | break; | 4272 | break; |
| 2960 | case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: | 4273 | case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: |
| 2961 | switch (state) { | 4274 | switch (state) { |
| 2962 | case MPI_PD_STATE_ONLINE: | 4275 | case MPI_PD_STATE_ONLINE: |
| 2963 | case MPI_PD_STATE_NOT_COMPATIBLE: | 4276 | case MPI_PD_STATE_NOT_COMPATIBLE: |
| 2964 | ev->phys_disk_num_valid = 1; | 4277 | mpt_raid_phys_disk_pg0(ioc, |
| 2965 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | 4278 | raid_event_data->PhysDiskNum, &phys_disk); |
| 2966 | ev->hidden_raid_component = 1; | 4279 | hot_plug_info.id = phys_disk.PhysDiskID; |
| 2967 | ev->event_type = MPTSAS_ADD_DEVICE; | 4280 | hot_plug_info.channel = phys_disk.PhysDiskBus; |
| 4281 | hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK; | ||
| 2968 | break; | 4282 | break; |
| 4283 | case MPI_PD_STATE_FAILED: | ||
| 2969 | case MPI_PD_STATE_MISSING: | 4284 | case MPI_PD_STATE_MISSING: |
| 2970 | case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: | 4285 | case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: |
| 2971 | case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: | 4286 | case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: |
| 2972 | case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: | 4287 | case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: |
| 2973 | ev->phys_disk_num_valid = 1; | 4288 | hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK; |
| 2974 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||
| 2975 | ev->event_type = MPTSAS_DEL_DEVICE; | ||
| 2976 | break; | 4289 | break; |
| 2977 | default: | 4290 | default: |
| 2978 | break; | 4291 | break; |
| 2979 | } | 4292 | } |
| 2980 | break; | 4293 | break; |
| 2981 | case MPI_EVENT_RAID_RC_VOLUME_DELETED: | 4294 | case MPI_EVENT_RAID_RC_VOLUME_DELETED: |
| 2982 | ev->event_type = MPTSAS_DEL_RAID; | 4295 | if (!sdev) |
| 4296 | break; | ||
| 4297 | vdevice->vtarget->deleted = 1; /* block IO */ | ||
| 4298 | hot_plug_info.event_type = MPTSAS_DEL_RAID; | ||
| 2983 | break; | 4299 | break; |
| 2984 | case MPI_EVENT_RAID_RC_VOLUME_CREATED: | 4300 | case MPI_EVENT_RAID_RC_VOLUME_CREATED: |
| 2985 | ev->event_type = MPTSAS_ADD_RAID; | 4301 | if (sdev) { |
| 4302 | scsi_device_put(sdev); | ||
| 4303 | break; | ||
| 4304 | } | ||
| 4305 | hot_plug_info.event_type = MPTSAS_ADD_RAID; | ||
| 2986 | break; | 4306 | break; |
| 2987 | case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED: | 4307 | case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED: |
| 4308 | if (!(status & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)) { | ||
| 4309 | if (!sdev) | ||
| 4310 | break; | ||
| 4311 | vdevice->vtarget->deleted = 1; /* block IO */ | ||
| 4312 | hot_plug_info.event_type = MPTSAS_DEL_RAID; | ||
| 4313 | break; | ||
| 4314 | } | ||
| 2988 | switch (state) { | 4315 | switch (state) { |
| 2989 | case MPI_RAIDVOL0_STATUS_STATE_FAILED: | 4316 | case MPI_RAIDVOL0_STATUS_STATE_FAILED: |
| 2990 | case MPI_RAIDVOL0_STATUS_STATE_MISSING: | 4317 | case MPI_RAIDVOL0_STATUS_STATE_MISSING: |
| 2991 | ev->event_type = MPTSAS_DEL_RAID; | 4318 | if (!sdev) |
| 4319 | break; | ||
| 4320 | vdevice->vtarget->deleted = 1; /* block IO */ | ||
| 4321 | hot_plug_info.event_type = MPTSAS_DEL_RAID; | ||
| 2992 | break; | 4322 | break; |
| 2993 | case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL: | 4323 | case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL: |
| 2994 | case MPI_RAIDVOL0_STATUS_STATE_DEGRADED: | 4324 | case MPI_RAIDVOL0_STATUS_STATE_DEGRADED: |
| 2995 | ev->event_type = MPTSAS_ADD_RAID; | 4325 | if (sdev) { |
| 4326 | scsi_device_put(sdev); | ||
| 4327 | break; | ||
| 4328 | } | ||
| 4329 | hot_plug_info.event_type = MPTSAS_ADD_RAID; | ||
| 2996 | break; | 4330 | break; |
| 2997 | default: | 4331 | default: |
| 2998 | break; | 4332 | break; |
| @@ -3001,32 +4335,188 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, | |||
| 3001 | default: | 4335 | default: |
| 3002 | break; | 4336 | break; |
| 3003 | } | 4337 | } |
| 3004 | schedule_work(&ev->work); | 4338 | |
| 4339 | if (hot_plug_info.event_type != MPTSAS_IGNORE_EVENT) | ||
| 4340 | mptsas_hotplug_work(ioc, fw_event, &hot_plug_info); | ||
| 4341 | else | ||
| 4342 | mptsas_free_fw_event(ioc, fw_event); | ||
| 3005 | } | 4343 | } |
| 3006 | 4344 | ||
| 3007 | static void | 4345 | /** |
| 3008 | mptsas_send_discovery_event(MPT_ADAPTER *ioc, | 4346 | * mptsas_issue_tm - send mptsas internal tm request |
| 3009 | EVENT_DATA_SAS_DISCOVERY *discovery_data) | 4347 | * @ioc: Pointer to MPT_ADAPTER structure |
| 4348 | * @type: Task Management type | ||
| 4349 | * @channel: channel number for task management | ||
| 4350 | * @id: Logical Target ID for reset (if appropriate) | ||
| 4351 | * @lun: Logical unit for reset (if appropriate) | ||
| 4352 | * @task_context: Context for the task to be aborted | ||
| 4353 | * @timeout: timeout for task management control | ||
| 4354 | * | ||
| 4355 | * return 0 on success and -1 on failure: | ||
| 4356 | * | ||
| 4357 | */ | ||
| 4358 | static int | ||
| 4359 | mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun, | ||
| 4360 | int task_context, ulong timeout, u8 *issue_reset) | ||
| 3010 | { | 4361 | { |
| 3011 | struct mptsas_discovery_event *ev; | 4362 | MPT_FRAME_HDR *mf; |
| 4363 | SCSITaskMgmt_t *pScsiTm; | ||
| 4364 | int retval; | ||
| 4365 | unsigned long timeleft; | ||
| 4366 | |||
| 4367 | *issue_reset = 0; | ||
| 4368 | mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc); | ||
| 4369 | if (mf == NULL) { | ||
| 4370 | retval = -1; /* return failure */ | ||
| 4371 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt request: no " | ||
| 4372 | "msg frames!!\n", ioc->name)); | ||
| 4373 | goto out; | ||
| 4374 | } | ||
| 3012 | 4375 | ||
| 3013 | /* | 4376 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request: mr = %p, " |
| 3014 | * DiscoveryStatus | 4377 | "task_type = 0x%02X,\n\t timeout = %ld, fw_channel = %d, " |
| 3015 | * | 4378 | "fw_id = %d, lun = %lld,\n\t task_context = 0x%x\n", ioc->name, mf, |
| 3016 | * This flag will be non-zero when firmware | 4379 | type, timeout, channel, id, (unsigned long long)lun, |
| 3017 | * kicks off discovery, and return to zero | 4380 | task_context)); |
| 3018 | * once its completed. | 4381 | |
| 3019 | */ | 4382 | pScsiTm = (SCSITaskMgmt_t *) mf; |
| 3020 | if (discovery_data->DiscoveryStatus) | 4383 | memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t)); |
| 3021 | return; | 4384 | pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; |
| 4385 | pScsiTm->TaskType = type; | ||
| 4386 | pScsiTm->MsgFlags = 0; | ||
| 4387 | pScsiTm->TargetID = id; | ||
| 4388 | pScsiTm->Bus = channel; | ||
| 4389 | pScsiTm->ChainOffset = 0; | ||
| 4390 | pScsiTm->Reserved = 0; | ||
| 4391 | pScsiTm->Reserved1 = 0; | ||
| 4392 | pScsiTm->TaskMsgContext = task_context; | ||
| 4393 | int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN); | ||
| 4394 | |||
| 4395 | INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status) | ||
| 4396 | CLEAR_MGMT_STATUS(ioc->internal_cmds.status) | ||
| 4397 | retval = 0; | ||
| 4398 | mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf); | ||
| 4399 | |||
| 4400 | /* Now wait for the command to complete */ | ||
| 4401 | timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, | ||
| 4402 | timeout*HZ); | ||
| 4403 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | ||
| 4404 | retval = -1; /* return failure */ | ||
| 4405 | dtmprintk(ioc, printk(MYIOC_s_ERR_FMT | ||
| 4406 | "TaskMgmt request: TIMED OUT!(mr=%p)\n", ioc->name, mf)); | ||
| 4407 | mpt_free_msg_frame(ioc, mf); | ||
| 4408 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) | ||
| 4409 | goto out; | ||
| 4410 | *issue_reset = 1; | ||
| 4411 | goto out; | ||
| 4412 | } | ||
| 3022 | 4413 | ||
| 3023 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | 4414 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { |
| 3024 | if (!ev) | 4415 | retval = -1; /* return failure */ |
| 4416 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 4417 | "TaskMgmt request: failed with no reply\n", ioc->name)); | ||
| 4418 | goto out; | ||
| 4419 | } | ||
| 4420 | |||
| 4421 | out: | ||
| 4422 | CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) | ||
| 4423 | return retval; | ||
| 4424 | } | ||
| 4425 | |||
| 4426 | /** | ||
| 4427 | * mptsas_broadcast_primative_work - Handle broadcast primitives | ||
| 4428 | * @work: work queue payload containing info describing the event | ||
| 4429 | * | ||
| 4430 | * this will be handled in workqueue context. | ||
| 4431 | */ | ||
| 4432 | static void | ||
| 4433 | mptsas_broadcast_primative_work(struct fw_event_work *fw_event) | ||
| 4434 | { | ||
| 4435 | MPT_ADAPTER *ioc = fw_event->ioc; | ||
| 4436 | MPT_FRAME_HDR *mf; | ||
| 4437 | VirtDevice *vdevice; | ||
| 4438 | int ii; | ||
| 4439 | struct scsi_cmnd *sc; | ||
| 4440 | SCSITaskMgmtReply_t *pScsiTmReply; | ||
| 4441 | u8 issue_reset; | ||
| 4442 | int task_context; | ||
| 4443 | u8 channel, id; | ||
| 4444 | int lun; | ||
| 4445 | u32 termination_count; | ||
| 4446 | u32 query_count; | ||
| 4447 | |||
| 4448 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 4449 | "%s - enter\n", ioc->name, __func__)); | ||
| 4450 | |||
| 4451 | mutex_lock(&ioc->taskmgmt_cmds.mutex); | ||
| 4452 | if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { | ||
| 4453 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | ||
| 4454 | mptsas_requeue_fw_event(ioc, fw_event, 1000); | ||
| 3025 | return; | 4455 | return; |
| 3026 | INIT_WORK(&ev->work, mptsas_discovery_work); | 4456 | } |
| 3027 | ev->ioc = ioc; | 4457 | |
| 3028 | schedule_work(&ev->work); | 4458 | issue_reset = 0; |
| 3029 | }; | 4459 | termination_count = 0; |
| 4460 | query_count = 0; | ||
| 4461 | mpt_findImVolumes(ioc); | ||
| 4462 | pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply; | ||
| 4463 | |||
| 4464 | for (ii = 0; ii < ioc->req_depth; ii++) { | ||
| 4465 | if (ioc->fw_events_off) | ||
| 4466 | goto out; | ||
| 4467 | sc = mptscsih_get_scsi_lookup(ioc, ii); | ||
| 4468 | if (!sc) | ||
| 4469 | continue; | ||
| 4470 | mf = MPT_INDEX_2_MFPTR(ioc, ii); | ||
| 4471 | if (!mf) | ||
| 4472 | continue; | ||
| 4473 | task_context = mf->u.frame.hwhdr.msgctxu.MsgContext; | ||
| 4474 | vdevice = sc->device->hostdata; | ||
| 4475 | if (!vdevice || !vdevice->vtarget) | ||
| 4476 | continue; | ||
| 4477 | if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) | ||
| 4478 | continue; /* skip hidden raid components */ | ||
| 4479 | if (vdevice->vtarget->raidVolume) | ||
| 4480 | continue; /* skip hidden raid components */ | ||
| 4481 | channel = vdevice->vtarget->channel; | ||
| 4482 | id = vdevice->vtarget->id; | ||
| 4483 | lun = vdevice->lun; | ||
| 4484 | if (mptsas_issue_tm(ioc, MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK, | ||
| 4485 | channel, id, (u64)lun, task_context, 30, &issue_reset)) | ||
| 4486 | goto out; | ||
| 4487 | query_count++; | ||
| 4488 | termination_count += | ||
| 4489 | le32_to_cpu(pScsiTmReply->TerminationCount); | ||
| 4490 | if ((pScsiTmReply->IOCStatus == MPI_IOCSTATUS_SUCCESS) && | ||
| 4491 | (pScsiTmReply->ResponseCode == | ||
| 4492 | MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED || | ||
| 4493 | pScsiTmReply->ResponseCode == | ||
| 4494 | MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) | ||
| 4495 | continue; | ||
| 4496 | if (mptsas_issue_tm(ioc, | ||
| 4497 | MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, | ||
| 4498 | channel, id, (u64)lun, 0, 30, &issue_reset)) | ||
| 4499 | goto out; | ||
| 4500 | termination_count += | ||
| 4501 | le32_to_cpu(pScsiTmReply->TerminationCount); | ||
| 4502 | } | ||
| 4503 | |||
| 4504 | out: | ||
| 4505 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 4506 | "%s - exit, query_count = %d termination_count = %d\n", | ||
| 4507 | ioc->name, __func__, query_count, termination_count)); | ||
| 4508 | |||
| 4509 | ioc->broadcast_aen_busy = 0; | ||
| 4510 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
| 4511 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | ||
| 4512 | |||
| 4513 | if (issue_reset) { | ||
| 4514 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", | ||
| 4515 | ioc->name, __func__); | ||
| 4516 | mpt_HardResetHandler(ioc, CAN_SLEEP); | ||
| 4517 | } | ||
| 4518 | mptsas_free_fw_event(ioc, fw_event); | ||
| 4519 | } | ||
| 3030 | 4520 | ||
| 3031 | /* | 4521 | /* |
| 3032 | * mptsas_send_ir2_event - handle exposing hidden disk when | 4522 | * mptsas_send_ir2_event - handle exposing hidden disk when |
| @@ -3037,76 +4527,159 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc, | |||
| 3037 | * | 4527 | * |
| 3038 | */ | 4528 | */ |
| 3039 | static void | 4529 | static void |
| 3040 | mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data) | 4530 | mptsas_send_ir2_event(struct fw_event_work *fw_event) |
| 3041 | { | 4531 | { |
| 3042 | struct mptsas_hotplug_event *ev; | 4532 | MPT_ADAPTER *ioc; |
| 3043 | 4533 | struct mptsas_hotplug_event hot_plug_info; | |
| 3044 | if (ir2_data->ReasonCode != | 4534 | MPI_EVENT_DATA_IR2 *ir2_data; |
| 3045 | MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED) | 4535 | u8 reasonCode; |
| 3046 | return; | 4536 | RaidPhysDiskPage0_t phys_disk; |
| 3047 | 4537 | ||
| 3048 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | 4538 | ioc = fw_event->ioc; |
| 3049 | if (!ev) | 4539 | ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data; |
| 4540 | reasonCode = ir2_data->ReasonCode; | ||
| 4541 | |||
| 4542 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: " | ||
| 4543 | "ReasonCode=%02x\n", ioc->name, __func__, reasonCode)); | ||
| 4544 | |||
| 4545 | memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event)); | ||
| 4546 | hot_plug_info.id = ir2_data->TargetID; | ||
| 4547 | hot_plug_info.channel = ir2_data->Bus; | ||
| 4548 | switch (reasonCode) { | ||
| 4549 | case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: | ||
| 4550 | hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME; | ||
| 4551 | break; | ||
| 4552 | case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED: | ||
| 4553 | hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum; | ||
| 4554 | hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK; | ||
| 4555 | break; | ||
| 4556 | case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED: | ||
| 4557 | hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum; | ||
| 4558 | mpt_raid_phys_disk_pg0(ioc, | ||
| 4559 | ir2_data->PhysDiskNum, &phys_disk); | ||
| 4560 | hot_plug_info.id = phys_disk.PhysDiskID; | ||
| 4561 | hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK; | ||
| 4562 | break; | ||
| 4563 | default: | ||
| 4564 | mptsas_free_fw_event(ioc, fw_event); | ||
| 3050 | return; | 4565 | return; |
| 3051 | 4566 | } | |
| 3052 | INIT_WORK(&ev->work, mptsas_hotplug_work); | 4567 | mptsas_hotplug_work(ioc, fw_event, &hot_plug_info); |
| 3053 | ev->ioc = ioc; | 4568 | } |
| 3054 | ev->id = ir2_data->TargetID; | ||
| 3055 | ev->channel = ir2_data->Bus; | ||
| 3056 | ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME; | ||
| 3057 | |||
| 3058 | schedule_work(&ev->work); | ||
| 3059 | }; | ||
| 3060 | 4569 | ||
| 3061 | static int | 4570 | static int |
| 3062 | mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | 4571 | mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) |
| 3063 | { | 4572 | { |
| 3064 | int rc=1; | 4573 | u32 event = le32_to_cpu(reply->Event); |
| 3065 | u8 event = le32_to_cpu(reply->Event) & 0xFF; | 4574 | int sz, event_data_sz; |
| 4575 | struct fw_event_work *fw_event; | ||
| 4576 | unsigned long delay; | ||
| 3066 | 4577 | ||
| 3067 | if (!ioc->sh) | 4578 | /* events turned off due to host reset or driver unloading */ |
| 3068 | goto out; | 4579 | if (ioc->fw_events_off) |
| 3069 | 4580 | return 0; | |
| 3070 | /* | ||
| 3071 | * sas_discovery_ignore_events | ||
| 3072 | * | ||
| 3073 | * This flag is to prevent anymore processing of | ||
| 3074 | * sas events once mptsas_remove function is called. | ||
| 3075 | */ | ||
| 3076 | if (ioc->sas_discovery_ignore_events) { | ||
| 3077 | rc = mptscsih_event_process(ioc, reply); | ||
| 3078 | goto out; | ||
| 3079 | } | ||
| 3080 | 4581 | ||
| 4582 | delay = msecs_to_jiffies(1); | ||
| 3081 | switch (event) { | 4583 | switch (event) { |
| 4584 | case MPI_EVENT_SAS_BROADCAST_PRIMITIVE: | ||
| 4585 | { | ||
| 4586 | EVENT_DATA_SAS_BROADCAST_PRIMITIVE *broadcast_event_data = | ||
| 4587 | (EVENT_DATA_SAS_BROADCAST_PRIMITIVE *)reply->Data; | ||
| 4588 | if (broadcast_event_data->Primitive != | ||
| 4589 | MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT) | ||
| 4590 | return 0; | ||
| 4591 | if (ioc->broadcast_aen_busy) | ||
| 4592 | return 0; | ||
| 4593 | ioc->broadcast_aen_busy = 1; | ||
| 4594 | break; | ||
| 4595 | } | ||
| 3082 | case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: | 4596 | case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: |
| 3083 | mptsas_send_sas_event(ioc, | 4597 | { |
| 3084 | (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data); | 4598 | EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data = |
| 4599 | (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data; | ||
| 4600 | |||
| 4601 | if (sas_event_data->ReasonCode == | ||
| 4602 | MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) { | ||
| 4603 | mptsas_target_reset_queue(ioc, sas_event_data); | ||
| 4604 | return 0; | ||
| 4605 | } | ||
| 3085 | break; | 4606 | break; |
| 3086 | case MPI_EVENT_INTEGRATED_RAID: | 4607 | } |
| 3087 | mptsas_send_raid_event(ioc, | 4608 | case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE: |
| 3088 | (EVENT_DATA_RAID *)reply->Data); | 4609 | { |
| 4610 | MpiEventDataSasExpanderStatusChange_t *expander_data = | ||
| 4611 | (MpiEventDataSasExpanderStatusChange_t *)reply->Data; | ||
| 4612 | |||
| 4613 | if (ioc->old_sas_discovery_protocal) | ||
| 4614 | return 0; | ||
| 4615 | |||
| 4616 | if (expander_data->ReasonCode == | ||
| 4617 | MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING && | ||
| 4618 | ioc->device_missing_delay) | ||
| 4619 | delay = HZ * ioc->device_missing_delay; | ||
| 3089 | break; | 4620 | break; |
| 4621 | } | ||
| 4622 | case MPI_EVENT_SAS_DISCOVERY: | ||
| 4623 | { | ||
| 4624 | u32 discovery_status; | ||
| 4625 | EventDataSasDiscovery_t *discovery_data = | ||
| 4626 | (EventDataSasDiscovery_t *)reply->Data; | ||
| 4627 | |||
| 4628 | discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus); | ||
| 4629 | ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0; | ||
| 4630 | if (ioc->old_sas_discovery_protocal && !discovery_status) | ||
| 4631 | mptsas_queue_rescan(ioc); | ||
| 4632 | return 0; | ||
| 4633 | } | ||
| 4634 | case MPI_EVENT_INTEGRATED_RAID: | ||
| 3090 | case MPI_EVENT_PERSISTENT_TABLE_FULL: | 4635 | case MPI_EVENT_PERSISTENT_TABLE_FULL: |
| 3091 | INIT_WORK(&ioc->sas_persist_task, | ||
| 3092 | mptsas_persist_clear_table); | ||
| 3093 | schedule_work(&ioc->sas_persist_task); | ||
| 3094 | break; | ||
| 3095 | case MPI_EVENT_SAS_DISCOVERY: | ||
| 3096 | mptsas_send_discovery_event(ioc, | ||
| 3097 | (EVENT_DATA_SAS_DISCOVERY *)reply->Data); | ||
| 3098 | break; | ||
| 3099 | case MPI_EVENT_IR2: | 4636 | case MPI_EVENT_IR2: |
| 3100 | mptsas_send_ir2_event(ioc, | 4637 | case MPI_EVENT_SAS_PHY_LINK_STATUS: |
| 3101 | (PTR_MPI_EVENT_DATA_IR2)reply->Data); | 4638 | case MPI_EVENT_QUEUE_FULL: |
| 3102 | break; | 4639 | break; |
| 3103 | default: | 4640 | default: |
| 3104 | rc = mptscsih_event_process(ioc, reply); | 4641 | return 0; |
| 3105 | break; | ||
| 3106 | } | 4642 | } |
| 3107 | out: | ||
| 3108 | 4643 | ||
| 3109 | return rc; | 4644 | event_data_sz = ((reply->MsgLength * 4) - |
| 4645 | offsetof(EventNotificationReply_t, Data)); | ||
| 4646 | sz = offsetof(struct fw_event_work, event_data) + event_data_sz; | ||
| 4647 | fw_event = kzalloc(sz, GFP_ATOMIC); | ||
| 4648 | if (!fw_event) { | ||
| 4649 | printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name, | ||
| 4650 | __func__, __LINE__); | ||
| 4651 | return 0; | ||
| 4652 | } | ||
| 4653 | memcpy(fw_event->event_data, reply->Data, event_data_sz); | ||
| 4654 | fw_event->event = event; | ||
| 4655 | fw_event->ioc = ioc; | ||
| 4656 | mptsas_add_fw_event(ioc, fw_event, delay); | ||
| 4657 | return 0; | ||
| 4658 | } | ||
| 4659 | |||
| 4660 | /* Delete a volume when no longer listed in ioc pg2 | ||
| 4661 | */ | ||
| 4662 | static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id) | ||
| 4663 | { | ||
| 4664 | struct scsi_device *sdev; | ||
| 4665 | int i; | ||
| 4666 | |||
| 4667 | sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0); | ||
| 4668 | if (!sdev) | ||
| 4669 | return; | ||
| 4670 | if (!ioc->raid_data.pIocPg2) | ||
| 4671 | goto out; | ||
| 4672 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | ||
| 4673 | goto out; | ||
| 4674 | for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) | ||
| 4675 | if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) | ||
| 4676 | goto release_sdev; | ||
| 4677 | out: | ||
| 4678 | printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, " | ||
| 4679 | "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id); | ||
| 4680 | scsi_remove_device(sdev); | ||
| 4681 | release_sdev: | ||
| 4682 | scsi_device_put(sdev); | ||
| 3110 | } | 4683 | } |
| 3111 | 4684 | ||
| 3112 | static int | 4685 | static int |
| @@ -3128,6 +4701,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 3128 | return r; | 4701 | return r; |
| 3129 | 4702 | ||
| 3130 | ioc = pci_get_drvdata(pdev); | 4703 | ioc = pci_get_drvdata(pdev); |
| 4704 | mptsas_fw_event_off(ioc); | ||
| 3131 | ioc->DoneCtx = mptsasDoneCtx; | 4705 | ioc->DoneCtx = mptsasDoneCtx; |
| 3132 | ioc->TaskCtx = mptsasTaskCtx; | 4706 | ioc->TaskCtx = mptsasTaskCtx; |
| 3133 | ioc->InternalCtx = mptsasInternalCtx; | 4707 | ioc->InternalCtx = mptsasInternalCtx; |
| @@ -3211,17 +4785,15 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 3211 | * A slightly different algorithm is required for | 4785 | * A slightly different algorithm is required for |
| 3212 | * 64bit SGEs. | 4786 | * 64bit SGEs. |
| 3213 | */ | 4787 | */ |
| 3214 | scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); | 4788 | scale = ioc->req_sz/ioc->SGE_size; |
| 3215 | if (sizeof(dma_addr_t) == sizeof(u64)) { | 4789 | if (ioc->sg_addr_size == sizeof(u64)) { |
| 3216 | numSGE = (scale - 1) * | 4790 | numSGE = (scale - 1) * |
| 3217 | (ioc->facts.MaxChainDepth-1) + scale + | 4791 | (ioc->facts.MaxChainDepth-1) + scale + |
| 3218 | (ioc->req_sz - 60) / (sizeof(dma_addr_t) + | 4792 | (ioc->req_sz - 60) / ioc->SGE_size; |
| 3219 | sizeof(u32)); | ||
| 3220 | } else { | 4793 | } else { |
| 3221 | numSGE = 1 + (scale - 1) * | 4794 | numSGE = 1 + (scale - 1) * |
| 3222 | (ioc->facts.MaxChainDepth-1) + scale + | 4795 | (ioc->facts.MaxChainDepth-1) + scale + |
| 3223 | (ioc->req_sz - 64) / (sizeof(dma_addr_t) + | 4796 | (ioc->req_sz - 64) / ioc->SGE_size; |
| 3224 | sizeof(u32)); | ||
| 3225 | } | 4797 | } |
| 3226 | 4798 | ||
| 3227 | if (numSGE < sh->sg_tablesize) { | 4799 | if (numSGE < sh->sg_tablesize) { |
| @@ -3251,9 +4823,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 3251 | 4823 | ||
| 3252 | /* Clear the TM flags | 4824 | /* Clear the TM flags |
| 3253 | */ | 4825 | */ |
| 3254 | hd->tmPending = 0; | ||
| 3255 | hd->tmState = TM_STATE_NONE; | ||
| 3256 | hd->resetPending = 0; | ||
| 3257 | hd->abortSCpnt = NULL; | 4826 | hd->abortSCpnt = NULL; |
| 3258 | 4827 | ||
| 3259 | /* Clear the pointer used to store | 4828 | /* Clear the pointer used to store |
| @@ -3273,10 +4842,11 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 3273 | 4842 | ||
| 3274 | ioc->sas_data.ptClear = mpt_pt_clear; | 4843 | ioc->sas_data.ptClear = mpt_pt_clear; |
| 3275 | 4844 | ||
| 3276 | init_waitqueue_head(&hd->scandv_waitq); | ||
| 3277 | hd->scandv_wait_done = 0; | ||
| 3278 | hd->last_queue_full = 0; | 4845 | hd->last_queue_full = 0; |
| 3279 | INIT_LIST_HEAD(&hd->target_reset_list); | 4846 | INIT_LIST_HEAD(&hd->target_reset_list); |
| 4847 | INIT_LIST_HEAD(&ioc->sas_device_info_list); | ||
| 4848 | mutex_init(&ioc->sas_device_info_mutex); | ||
| 4849 | |||
| 3280 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 4850 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); |
| 3281 | 4851 | ||
| 3282 | if (ioc->sas_data.ptClear==1) { | 4852 | if (ioc->sas_data.ptClear==1) { |
| @@ -3291,8 +4861,11 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 3291 | goto out_mptsas_probe; | 4861 | goto out_mptsas_probe; |
| 3292 | } | 4862 | } |
| 3293 | 4863 | ||
| 4864 | /* older firmware doesn't support expander events */ | ||
| 4865 | if ((ioc->facts.HeaderVersion >> 8) < 0xE) | ||
| 4866 | ioc->old_sas_discovery_protocal = 1; | ||
| 3294 | mptsas_scan_sas_topology(ioc); | 4867 | mptsas_scan_sas_topology(ioc); |
| 3295 | 4868 | mptsas_fw_event_on(ioc); | |
| 3296 | return 0; | 4869 | return 0; |
| 3297 | 4870 | ||
| 3298 | out_mptsas_probe: | 4871 | out_mptsas_probe: |
| @@ -3301,12 +4874,25 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 3301 | return error; | 4874 | return error; |
| 3302 | } | 4875 | } |
| 3303 | 4876 | ||
| 4877 | void | ||
| 4878 | mptsas_shutdown(struct pci_dev *pdev) | ||
| 4879 | { | ||
| 4880 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | ||
| 4881 | |||
| 4882 | mptsas_fw_event_off(ioc); | ||
| 4883 | mptsas_cleanup_fw_event_q(ioc); | ||
| 4884 | } | ||
| 4885 | |||
| 3304 | static void __devexit mptsas_remove(struct pci_dev *pdev) | 4886 | static void __devexit mptsas_remove(struct pci_dev *pdev) |
| 3305 | { | 4887 | { |
| 3306 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | 4888 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); |
| 3307 | struct mptsas_portinfo *p, *n; | 4889 | struct mptsas_portinfo *p, *n; |
| 3308 | int i; | 4890 | int i; |
| 3309 | 4891 | ||
| 4892 | mptsas_shutdown(pdev); | ||
| 4893 | |||
| 4894 | mptsas_del_device_components(ioc); | ||
| 4895 | |||
| 3310 | ioc->sas_discovery_ignore_events = 1; | 4896 | ioc->sas_discovery_ignore_events = 1; |
| 3311 | sas_remove_host(ioc->sh); | 4897 | sas_remove_host(ioc->sh); |
| 3312 | 4898 | ||
| @@ -3315,11 +4901,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) | |||
| 3315 | list_del(&p->list); | 4901 | list_del(&p->list); |
| 3316 | for (i = 0 ; i < p->num_phys ; i++) | 4902 | for (i = 0 ; i < p->num_phys ; i++) |
| 3317 | mptsas_port_delete(ioc, p->phy_info[i].port_details); | 4903 | mptsas_port_delete(ioc, p->phy_info[i].port_details); |
| 4904 | |||
| 3318 | kfree(p->phy_info); | 4905 | kfree(p->phy_info); |
| 3319 | kfree(p); | 4906 | kfree(p); |
| 3320 | } | 4907 | } |
| 3321 | mutex_unlock(&ioc->sas_topology_mutex); | 4908 | mutex_unlock(&ioc->sas_topology_mutex); |
| 3322 | 4909 | ioc->hba_port_info = NULL; | |
| 3323 | mptscsih_remove(pdev); | 4910 | mptscsih_remove(pdev); |
| 3324 | } | 4911 | } |
| 3325 | 4912 | ||
| @@ -3344,7 +4931,7 @@ static struct pci_driver mptsas_driver = { | |||
| 3344 | .id_table = mptsas_pci_table, | 4931 | .id_table = mptsas_pci_table, |
| 3345 | .probe = mptsas_probe, | 4932 | .probe = mptsas_probe, |
| 3346 | .remove = __devexit_p(mptsas_remove), | 4933 | .remove = __devexit_p(mptsas_remove), |
| 3347 | .shutdown = mptscsih_shutdown, | 4934 | .shutdown = mptsas_shutdown, |
| 3348 | #ifdef CONFIG_PM | 4935 | #ifdef CONFIG_PM |
| 3349 | .suspend = mptscsih_suspend, | 4936 | .suspend = mptscsih_suspend, |
| 3350 | .resume = mptscsih_resume, | 4937 | .resume = mptscsih_resume, |
| @@ -3364,10 +4951,12 @@ mptsas_init(void) | |||
| 3364 | return -ENODEV; | 4951 | return -ENODEV; |
| 3365 | 4952 | ||
| 3366 | mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); | 4953 | mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); |
| 3367 | mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER); | 4954 | mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); |
| 3368 | mptsasInternalCtx = | 4955 | mptsasInternalCtx = |
| 3369 | mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); | 4956 | mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); |
| 3370 | mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); | 4957 | mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); |
| 4958 | mptsasDeviceResetCtx = | ||
| 4959 | mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER); | ||
| 3371 | 4960 | ||
| 3372 | mpt_event_register(mptsasDoneCtx, mptsas_event_process); | 4961 | mpt_event_register(mptsasDoneCtx, mptsas_event_process); |
| 3373 | mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset); | 4962 | mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset); |
| @@ -3392,6 +4981,7 @@ mptsas_exit(void) | |||
| 3392 | mpt_deregister(mptsasInternalCtx); | 4981 | mpt_deregister(mptsasInternalCtx); |
| 3393 | mpt_deregister(mptsasTaskCtx); | 4982 | mpt_deregister(mptsasTaskCtx); |
| 3394 | mpt_deregister(mptsasDoneCtx); | 4983 | mpt_deregister(mptsasDoneCtx); |
| 4984 | mpt_deregister(mptsasDeviceResetCtx); | ||
| 3395 | } | 4985 | } |
| 3396 | 4986 | ||
| 3397 | module_init(mptsas_init); | 4987 | module_init(mptsas_init); |
diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h index 2b544e0877e6..953c2bfcf6aa 100644 --- a/drivers/message/fusion/mptsas.h +++ b/drivers/message/fusion/mptsas.h | |||
| @@ -53,6 +53,7 @@ struct mptsas_target_reset_event { | |||
| 53 | struct list_head list; | 53 | struct list_head list; |
| 54 | EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data; | 54 | EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data; |
| 55 | u8 target_reset_issued; | 55 | u8 target_reset_issued; |
| 56 | unsigned long time_count; | ||
| 56 | }; | 57 | }; |
| 57 | 58 | ||
| 58 | enum mptsas_hotplug_action { | 59 | enum mptsas_hotplug_action { |
| @@ -60,12 +61,37 @@ enum mptsas_hotplug_action { | |||
| 60 | MPTSAS_DEL_DEVICE, | 61 | MPTSAS_DEL_DEVICE, |
| 61 | MPTSAS_ADD_RAID, | 62 | MPTSAS_ADD_RAID, |
| 62 | MPTSAS_DEL_RAID, | 63 | MPTSAS_DEL_RAID, |
| 64 | MPTSAS_ADD_PHYSDISK, | ||
| 65 | MPTSAS_ADD_PHYSDISK_REPROBE, | ||
| 66 | MPTSAS_DEL_PHYSDISK, | ||
| 67 | MPTSAS_DEL_PHYSDISK_REPROBE, | ||
| 63 | MPTSAS_ADD_INACTIVE_VOLUME, | 68 | MPTSAS_ADD_INACTIVE_VOLUME, |
| 64 | MPTSAS_IGNORE_EVENT, | 69 | MPTSAS_IGNORE_EVENT, |
| 65 | }; | 70 | }; |
| 66 | 71 | ||
| 72 | struct mptsas_mapping{ | ||
| 73 | u8 id; | ||
| 74 | u8 channel; | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct mptsas_device_info { | ||
| 78 | struct list_head list; | ||
| 79 | struct mptsas_mapping os; /* operating system mapping*/ | ||
| 80 | struct mptsas_mapping fw; /* firmware mapping */ | ||
| 81 | u64 sas_address; | ||
| 82 | u32 device_info; /* specific bits for devices */ | ||
| 83 | u16 slot; /* enclosure slot id */ | ||
| 84 | u64 enclosure_logical_id; /*enclosure address */ | ||
| 85 | u8 is_logical_volume; /* is this logical volume */ | ||
| 86 | /* this belongs to volume */ | ||
| 87 | u8 is_hidden_raid_component; | ||
| 88 | /* this valid when is_hidden_raid_component set */ | ||
| 89 | u8 volume_id; | ||
| 90 | /* cached data for a removed device */ | ||
| 91 | u8 is_cached; | ||
| 92 | }; | ||
| 93 | |||
| 67 | struct mptsas_hotplug_event { | 94 | struct mptsas_hotplug_event { |
| 68 | struct work_struct work; | ||
| 69 | MPT_ADAPTER *ioc; | 95 | MPT_ADAPTER *ioc; |
| 70 | enum mptsas_hotplug_action event_type; | 96 | enum mptsas_hotplug_action event_type; |
| 71 | u64 sas_address; | 97 | u64 sas_address; |
| @@ -73,11 +99,18 @@ struct mptsas_hotplug_event { | |||
| 73 | u8 id; | 99 | u8 id; |
| 74 | u32 device_info; | 100 | u32 device_info; |
| 75 | u16 handle; | 101 | u16 handle; |
| 76 | u16 parent_handle; | ||
| 77 | u8 phy_id; | 102 | u8 phy_id; |
| 78 | u8 phys_disk_num_valid; /* hrc (hidden raid component) */ | ||
| 79 | u8 phys_disk_num; /* hrc - unique index*/ | 103 | u8 phys_disk_num; /* hrc - unique index*/ |
| 80 | u8 hidden_raid_component; /* hrc - don't expose*/ | 104 | struct scsi_device *sdev; |
| 105 | }; | ||
| 106 | |||
| 107 | struct fw_event_work { | ||
| 108 | struct list_head list; | ||
| 109 | struct delayed_work work; | ||
| 110 | MPT_ADAPTER *ioc; | ||
| 111 | u32 event; | ||
| 112 | u8 retries; | ||
| 113 | u8 event_data[1]; | ||
| 81 | }; | 114 | }; |
| 82 | 115 | ||
| 83 | struct mptsas_discovery_event { | 116 | struct mptsas_discovery_event { |
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index e62c6bc4ad33..024e8305bcf2 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
| @@ -80,7 +80,7 @@ MODULE_VERSION(my_VERSION); | |||
| 80 | /* | 80 | /* |
| 81 | * Other private/forward protos... | 81 | * Other private/forward protos... |
| 82 | */ | 82 | */ |
| 83 | static struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i); | 83 | struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i); |
| 84 | static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i); | 84 | static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i); |
| 85 | static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd); | 85 | static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd); |
| 86 | static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd); | 86 | static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd); |
| @@ -92,18 +92,24 @@ static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, | |||
| 92 | SCSIIORequest_t *pReq, int req_idx); | 92 | SCSIIORequest_t *pReq, int req_idx); |
| 93 | static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); | 93 | static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); |
| 94 | static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); | 94 | static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); |
| 95 | static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); | ||
| 96 | static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); | ||
| 97 | 95 | ||
| 98 | static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); | 96 | int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, |
| 97 | int lun, int ctx2abort, ulong timeout); | ||
| 99 | 98 | ||
| 100 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); | 99 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); |
| 101 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); | 100 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); |
| 102 | 101 | ||
| 102 | void | ||
| 103 | mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code); | ||
| 104 | static int mptscsih_get_completion_code(MPT_ADAPTER *ioc, | ||
| 105 | MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); | ||
| 103 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); | 106 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); |
| 104 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); | 107 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); |
| 105 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); | 108 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); |
| 106 | 109 | ||
| 110 | static int | ||
| 111 | mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type, | ||
| 112 | SCSITaskMgmtReply_t *pScsiTmReply); | ||
| 107 | void mptscsih_remove(struct pci_dev *); | 113 | void mptscsih_remove(struct pci_dev *); |
| 108 | void mptscsih_shutdown(struct pci_dev *); | 114 | void mptscsih_shutdown(struct pci_dev *); |
| 109 | #ifdef CONFIG_PM | 115 | #ifdef CONFIG_PM |
| @@ -113,69 +119,6 @@ int mptscsih_resume(struct pci_dev *pdev); | |||
| 113 | 119 | ||
| 114 | #define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE | 120 | #define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE |
| 115 | 121 | ||
| 116 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
| 117 | /** | ||
| 118 | * mptscsih_add_sge - Place a simple SGE at address pAddr. | ||
| 119 | * @pAddr: virtual address for SGE | ||
| 120 | * @flagslength: SGE flags and data transfer length | ||
| 121 | * @dma_addr: Physical address | ||
| 122 | * | ||
| 123 | * This routine places a MPT request frame back on the MPT adapter's | ||
| 124 | * FreeQ. | ||
| 125 | */ | ||
| 126 | static inline void | ||
| 127 | mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) | ||
| 128 | { | ||
| 129 | if (sizeof(dma_addr_t) == sizeof(u64)) { | ||
| 130 | SGESimple64_t *pSge = (SGESimple64_t *) pAddr; | ||
| 131 | u32 tmp = dma_addr & 0xFFFFFFFF; | ||
| 132 | |||
| 133 | pSge->FlagsLength = cpu_to_le32(flagslength); | ||
| 134 | pSge->Address.Low = cpu_to_le32(tmp); | ||
| 135 | tmp = (u32) ((u64)dma_addr >> 32); | ||
| 136 | pSge->Address.High = cpu_to_le32(tmp); | ||
| 137 | |||
| 138 | } else { | ||
| 139 | SGESimple32_t *pSge = (SGESimple32_t *) pAddr; | ||
| 140 | pSge->FlagsLength = cpu_to_le32(flagslength); | ||
| 141 | pSge->Address = cpu_to_le32(dma_addr); | ||
| 142 | } | ||
| 143 | } /* mptscsih_add_sge() */ | ||
| 144 | |||
| 145 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
| 146 | /** | ||
| 147 | * mptscsih_add_chain - Place a chain SGE at address pAddr. | ||
| 148 | * @pAddr: virtual address for SGE | ||
| 149 | * @next: nextChainOffset value (u32's) | ||
| 150 | * @length: length of next SGL segment | ||
| 151 | * @dma_addr: Physical address | ||
| 152 | * | ||
| 153 | * This routine places a MPT request frame back on the MPT adapter's | ||
| 154 | * FreeQ. | ||
| 155 | */ | ||
| 156 | static inline void | ||
| 157 | mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr) | ||
| 158 | { | ||
| 159 | if (sizeof(dma_addr_t) == sizeof(u64)) { | ||
| 160 | SGEChain64_t *pChain = (SGEChain64_t *) pAddr; | ||
| 161 | u32 tmp = dma_addr & 0xFFFFFFFF; | ||
| 162 | |||
| 163 | pChain->Length = cpu_to_le16(length); | ||
| 164 | pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); | ||
| 165 | |||
| 166 | pChain->NextChainOffset = next; | ||
| 167 | |||
| 168 | pChain->Address.Low = cpu_to_le32(tmp); | ||
| 169 | tmp = (u32) ((u64)dma_addr >> 32); | ||
| 170 | pChain->Address.High = cpu_to_le32(tmp); | ||
| 171 | } else { | ||
| 172 | SGEChain32_t *pChain = (SGEChain32_t *) pAddr; | ||
| 173 | pChain->Length = cpu_to_le16(length); | ||
| 174 | pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); | ||
| 175 | pChain->NextChainOffset = next; | ||
| 176 | pChain->Address = cpu_to_le32(dma_addr); | ||
| 177 | } | ||
| 178 | } /* mptscsih_add_chain() */ | ||
| 179 | 122 | ||
| 180 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 123 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 181 | /* | 124 | /* |
| @@ -281,10 +224,10 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, | |||
| 281 | */ | 224 | */ |
| 282 | 225 | ||
| 283 | nextSGEset: | 226 | nextSGEset: |
| 284 | numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) ); | 227 | numSgeSlots = ((frm_sz - sgeOffset) / ioc->SGE_size); |
| 285 | numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots; | 228 | numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots; |
| 286 | 229 | ||
| 287 | sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir; | 230 | sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | sgdir; |
| 288 | 231 | ||
| 289 | /* Get first (num - 1) SG elements | 232 | /* Get first (num - 1) SG elements |
| 290 | * Skip any SG entries with a length of 0 | 233 | * Skip any SG entries with a length of 0 |
| @@ -293,17 +236,19 @@ nextSGEset: | |||
| 293 | for (ii=0; ii < (numSgeThisFrame-1); ii++) { | 236 | for (ii=0; ii < (numSgeThisFrame-1); ii++) { |
| 294 | thisxfer = sg_dma_len(sg); | 237 | thisxfer = sg_dma_len(sg); |
| 295 | if (thisxfer == 0) { | 238 | if (thisxfer == 0) { |
| 296 | sg = sg_next(sg); /* Get next SG element from the OS */ | 239 | /* Get next SG element from the OS */ |
| 240 | sg = sg_next(sg); | ||
| 297 | sg_done++; | 241 | sg_done++; |
| 298 | continue; | 242 | continue; |
| 299 | } | 243 | } |
| 300 | 244 | ||
| 301 | v2 = sg_dma_address(sg); | 245 | v2 = sg_dma_address(sg); |
| 302 | mptscsih_add_sge(psge, sgflags | thisxfer, v2); | 246 | ioc->add_sge(psge, sgflags | thisxfer, v2); |
| 303 | 247 | ||
| 304 | sg = sg_next(sg); /* Get next SG element from the OS */ | 248 | /* Get next SG element from the OS */ |
| 305 | psge += (sizeof(u32) + sizeof(dma_addr_t)); | 249 | sg = sg_next(sg); |
| 306 | sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); | 250 | psge += ioc->SGE_size; |
| 251 | sgeOffset += ioc->SGE_size; | ||
| 307 | sg_done++; | 252 | sg_done++; |
| 308 | } | 253 | } |
| 309 | 254 | ||
| @@ -320,12 +265,8 @@ nextSGEset: | |||
| 320 | thisxfer = sg_dma_len(sg); | 265 | thisxfer = sg_dma_len(sg); |
| 321 | 266 | ||
| 322 | v2 = sg_dma_address(sg); | 267 | v2 = sg_dma_address(sg); |
| 323 | mptscsih_add_sge(psge, sgflags | thisxfer, v2); | 268 | ioc->add_sge(psge, sgflags | thisxfer, v2); |
| 324 | /* | 269 | sgeOffset += ioc->SGE_size; |
| 325 | sg = sg_next(sg); | ||
| 326 | psge += (sizeof(u32) + sizeof(dma_addr_t)); | ||
| 327 | */ | ||
| 328 | sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); | ||
| 329 | sg_done++; | 270 | sg_done++; |
| 330 | 271 | ||
| 331 | if (chainSge) { | 272 | if (chainSge) { |
| @@ -334,7 +275,8 @@ nextSGEset: | |||
| 334 | * Update the chain element | 275 | * Update the chain element |
| 335 | * Offset and Length fields. | 276 | * Offset and Length fields. |
| 336 | */ | 277 | */ |
| 337 | mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off); | 278 | ioc->add_chain((char *)chainSge, 0, sgeOffset, |
| 279 | ioc->ChainBufferDMA + chain_dma_off); | ||
| 338 | } else { | 280 | } else { |
| 339 | /* The current buffer is the original MF | 281 | /* The current buffer is the original MF |
| 340 | * and there is no Chain buffer. | 282 | * and there is no Chain buffer. |
| @@ -367,7 +309,7 @@ nextSGEset: | |||
| 367 | * set properly). | 309 | * set properly). |
| 368 | */ | 310 | */ |
| 369 | if (sg_done) { | 311 | if (sg_done) { |
| 370 | u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t))); | 312 | u32 *ptmp = (u32 *) (psge - ioc->SGE_size); |
| 371 | sgflags = le32_to_cpu(*ptmp); | 313 | sgflags = le32_to_cpu(*ptmp); |
| 372 | sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT; | 314 | sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT; |
| 373 | *ptmp = cpu_to_le32(sgflags); | 315 | *ptmp = cpu_to_le32(sgflags); |
| @@ -381,8 +323,9 @@ nextSGEset: | |||
| 381 | * Old chain element is now complete. | 323 | * Old chain element is now complete. |
| 382 | */ | 324 | */ |
| 383 | u8 nextChain = (u8) (sgeOffset >> 2); | 325 | u8 nextChain = (u8) (sgeOffset >> 2); |
| 384 | sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); | 326 | sgeOffset += ioc->SGE_size; |
| 385 | mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off); | 327 | ioc->add_chain((char *)chainSge, nextChain, sgeOffset, |
| 328 | ioc->ChainBufferDMA + chain_dma_off); | ||
| 386 | } else { | 329 | } else { |
| 387 | /* The original MF buffer requires a chain buffer - | 330 | /* The original MF buffer requires a chain buffer - |
| 388 | * set the offset. | 331 | * set the offset. |
| @@ -592,14 +535,15 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc | |||
| 592 | } | 535 | } |
| 593 | 536 | ||
| 594 | scsi_print_command(sc); | 537 | scsi_print_command(sc); |
| 595 | printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d\n", | 538 | printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %d\n", |
| 596 | ioc->name, pScsiReply->Bus, pScsiReply->TargetID); | 539 | ioc->name, pScsiReply->Bus, pScsiReply->TargetID, sc->device->lun); |
| 597 | printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, " | 540 | printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, " |
| 598 | "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow, | 541 | "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow, |
| 599 | scsi_get_resid(sc)); | 542 | scsi_get_resid(sc)); |
| 600 | printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, " | 543 | printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, " |
| 601 | "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag), | 544 | "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag), |
| 602 | le32_to_cpu(pScsiReply->TransferCount), sc->result); | 545 | le32_to_cpu(pScsiReply->TransferCount), sc->result); |
| 546 | |||
| 603 | printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), " | 547 | printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), " |
| 604 | "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n", | 548 | "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n", |
| 605 | ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus, | 549 | ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus, |
| @@ -654,16 +598,14 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
| 654 | req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); | 598 | req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); |
| 655 | req_idx_MR = (mr != NULL) ? | 599 | req_idx_MR = (mr != NULL) ? |
| 656 | le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx; | 600 | le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx; |
| 601 | |||
| 602 | /* Special case, where already freed message frame is received from | ||
| 603 | * Firmware. It happens with Resetting IOC. | ||
| 604 | * Return immediately. Do not care | ||
| 605 | */ | ||
| 657 | if ((req_idx != req_idx_MR) || | 606 | if ((req_idx != req_idx_MR) || |
| 658 | (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) { | 607 | (le32_to_cpu(mf->u.frame.linkage.arg1) == 0xdeadbeaf)) |
| 659 | printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n", | ||
| 660 | ioc->name); | ||
| 661 | printk (MYIOC_s_ERR_FMT | ||
| 662 | "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n", | ||
| 663 | ioc->name, req_idx, req_idx_MR, mf, mr, | ||
| 664 | mptscsih_get_scsi_lookup(ioc, req_idx_MR)); | ||
| 665 | return 0; | 608 | return 0; |
| 666 | } | ||
| 667 | 609 | ||
| 668 | sc = mptscsih_getclear_scsi_lookup(ioc, req_idx); | 610 | sc = mptscsih_getclear_scsi_lookup(ioc, req_idx); |
| 669 | if (sc == NULL) { | 611 | if (sc == NULL) { |
| @@ -810,12 +752,16 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
| 810 | */ | 752 | */ |
| 811 | 753 | ||
| 812 | case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ | 754 | case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ |
| 813 | case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ | ||
| 814 | /* Linux handles an unsolicited DID_RESET better | 755 | /* Linux handles an unsolicited DID_RESET better |
| 815 | * than an unsolicited DID_ABORT. | 756 | * than an unsolicited DID_ABORT. |
| 816 | */ | 757 | */ |
| 817 | sc->result = DID_RESET << 16; | 758 | sc->result = DID_RESET << 16; |
| 818 | 759 | ||
| 760 | case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ | ||
| 761 | if (ioc->bus_type == FC) | ||
| 762 | sc->result = DID_ERROR << 16; | ||
| 763 | else | ||
| 764 | sc->result = DID_RESET << 16; | ||
| 819 | break; | 765 | break; |
| 820 | 766 | ||
| 821 | case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ | 767 | case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ |
| @@ -992,9 +938,9 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) | |||
| 992 | scsi_dma_unmap(sc); | 938 | scsi_dma_unmap(sc); |
| 993 | sc->result = DID_RESET << 16; | 939 | sc->result = DID_RESET << 16; |
| 994 | sc->host_scribble = NULL; | 940 | sc->host_scribble = NULL; |
| 995 | sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT | 941 | dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT |
| 996 | "completing cmds: fw_channel %d, fw_id %d, sc=%p," | 942 | "completing cmds: fw_channel %d, fw_id %d, sc=%p, mf = %p, " |
| 997 | " mf = %p, idx=%x\n", ioc->name, channel, id, sc, mf, ii); | 943 | "idx=%x\n", ioc->name, channel, id, sc, mf, ii)); |
| 998 | sc->scsi_done(sc); | 944 | sc->scsi_done(sc); |
| 999 | } | 945 | } |
| 1000 | } | 946 | } |
| @@ -1053,9 +999,11 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) | |||
| 1053 | scsi_dma_unmap(sc); | 999 | scsi_dma_unmap(sc); |
| 1054 | sc->host_scribble = NULL; | 1000 | sc->host_scribble = NULL; |
| 1055 | sc->result = DID_NO_CONNECT << 16; | 1001 | sc->result = DID_NO_CONNECT << 16; |
| 1056 | sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT "completing cmds: fw_channel %d," | 1002 | dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, |
| 1057 | "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel, | 1003 | MYIOC_s_FMT "completing cmds: fw_channel %d, " |
| 1058 | vdevice->vtarget->id, sc, mf, ii); | 1004 | "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, |
| 1005 | vdevice->vtarget->channel, vdevice->vtarget->id, | ||
| 1006 | sc, mf, ii)); | ||
| 1059 | sc->scsi_done(sc); | 1007 | sc->scsi_done(sc); |
| 1060 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 1008 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
| 1061 | } | 1009 | } |
| @@ -1346,7 +1294,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
| 1346 | MPT_FRAME_HDR *mf; | 1294 | MPT_FRAME_HDR *mf; |
| 1347 | SCSIIORequest_t *pScsiReq; | 1295 | SCSIIORequest_t *pScsiReq; |
| 1348 | VirtDevice *vdevice = SCpnt->device->hostdata; | 1296 | VirtDevice *vdevice = SCpnt->device->hostdata; |
| 1349 | int lun; | ||
| 1350 | u32 datalen; | 1297 | u32 datalen; |
| 1351 | u32 scsictl; | 1298 | u32 scsictl; |
| 1352 | u32 scsidir; | 1299 | u32 scsidir; |
| @@ -1357,13 +1304,12 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
| 1357 | 1304 | ||
| 1358 | hd = shost_priv(SCpnt->device->host); | 1305 | hd = shost_priv(SCpnt->device->host); |
| 1359 | ioc = hd->ioc; | 1306 | ioc = hd->ioc; |
| 1360 | lun = SCpnt->device->lun; | ||
| 1361 | SCpnt->scsi_done = done; | 1307 | SCpnt->scsi_done = done; |
| 1362 | 1308 | ||
| 1363 | dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n", | 1309 | dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n", |
| 1364 | ioc->name, SCpnt, done)); | 1310 | ioc->name, SCpnt, done)); |
| 1365 | 1311 | ||
| 1366 | if (hd->resetPending) { | 1312 | if (ioc->taskmgmt_quiesce_io) { |
| 1367 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", | 1313 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", |
| 1368 | ioc->name, SCpnt)); | 1314 | ioc->name, SCpnt)); |
| 1369 | return SCSI_MLQUEUE_HOST_BUSY; | 1315 | return SCSI_MLQUEUE_HOST_BUSY; |
| @@ -1422,7 +1368,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
| 1422 | pScsiReq->CDBLength = SCpnt->cmd_len; | 1368 | pScsiReq->CDBLength = SCpnt->cmd_len; |
| 1423 | pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; | 1369 | pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; |
| 1424 | pScsiReq->Reserved = 0; | 1370 | pScsiReq->Reserved = 0; |
| 1425 | pScsiReq->MsgFlags = mpt_msg_flags(); | 1371 | pScsiReq->MsgFlags = mpt_msg_flags(ioc); |
| 1426 | int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN); | 1372 | int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN); |
| 1427 | pScsiReq->Control = cpu_to_le32(scsictl); | 1373 | pScsiReq->Control = cpu_to_le32(scsictl); |
| 1428 | 1374 | ||
| @@ -1448,7 +1394,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
| 1448 | */ | 1394 | */ |
| 1449 | if (datalen == 0) { | 1395 | if (datalen == 0) { |
| 1450 | /* Add a NULL SGE */ | 1396 | /* Add a NULL SGE */ |
| 1451 | mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0, | 1397 | ioc->add_sge((char *)&pScsiReq->SGL, |
| 1398 | MPT_SGE_FLAGS_SSIMPLE_READ | 0, | ||
| 1452 | (dma_addr_t) -1); | 1399 | (dma_addr_t) -1); |
| 1453 | } else { | 1400 | } else { |
| 1454 | /* Add a 32 or 64 bit SGE */ | 1401 | /* Add a 32 or 64 bit SGE */ |
| @@ -1528,8 +1475,8 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) | |||
| 1528 | 1475 | ||
| 1529 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1476 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 1530 | /** | 1477 | /** |
| 1531 | * mptscsih_TMHandler - Generic handler for SCSI Task Management. | 1478 | * mptscsih_IssueTaskMgmt - Generic send Task Management function. |
| 1532 | * @hd: Pointer to MPT SCSI HOST structure | 1479 | * @hd: Pointer to MPT_SCSI_HOST structure |
| 1533 | * @type: Task Management type | 1480 | * @type: Task Management type |
| 1534 | * @channel: channel number for task management | 1481 | * @channel: channel number for task management |
| 1535 | * @id: Logical Target ID for reset (if appropriate) | 1482 | * @id: Logical Target ID for reset (if appropriate) |
| @@ -1537,145 +1484,68 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) | |||
| 1537 | * @ctx2abort: Context for the task to be aborted (if appropriate) | 1484 | * @ctx2abort: Context for the task to be aborted (if appropriate) |
| 1538 | * @timeout: timeout for task management control | 1485 | * @timeout: timeout for task management control |
| 1539 | * | 1486 | * |
| 1540 | * Fall through to mpt_HardResetHandler if: not operational, too many | 1487 | * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) |
| 1541 | * failed TM requests or handshake failure. | 1488 | * or a non-interrupt thread. In the former, must not call schedule(). |
| 1542 | * | 1489 | * |
| 1543 | * Remark: Currently invoked from a non-interrupt thread (_bh). | 1490 | * Not all fields are meaningfull for all task types. |
| 1544 | * | 1491 | * |
| 1545 | * Note: With old EH code, at most 1 SCSI TaskMgmt function per IOC | 1492 | * Returns 0 for SUCCESS, or FAILED. |
| 1546 | * will be active. | ||
| 1547 | * | 1493 | * |
| 1548 | * Returns 0 for SUCCESS, or %FAILED. | ||
| 1549 | **/ | 1494 | **/ |
| 1550 | int | 1495 | int |
| 1551 | mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) | 1496 | mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, |
| 1497 | int ctx2abort, ulong timeout) | ||
| 1552 | { | 1498 | { |
| 1553 | MPT_ADAPTER *ioc; | 1499 | MPT_FRAME_HDR *mf; |
| 1554 | int rc = -1; | 1500 | SCSITaskMgmt_t *pScsiTm; |
| 1501 | int ii; | ||
| 1502 | int retval; | ||
| 1503 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 1504 | unsigned long timeleft; | ||
| 1505 | u8 issue_hard_reset; | ||
| 1555 | u32 ioc_raw_state; | 1506 | u32 ioc_raw_state; |
| 1556 | unsigned long flags; | 1507 | unsigned long time_count; |
| 1557 | |||
| 1558 | ioc = hd->ioc; | ||
| 1559 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler Entered!\n", ioc->name)); | ||
| 1560 | |||
| 1561 | // SJR - CHECKME - Can we avoid this here? | ||
| 1562 | // (mpt_HardResetHandler has this check...) | ||
| 1563 | spin_lock_irqsave(&ioc->diagLock, flags); | ||
| 1564 | if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) { | ||
| 1565 | spin_unlock_irqrestore(&ioc->diagLock, flags); | ||
| 1566 | return FAILED; | ||
| 1567 | } | ||
| 1568 | spin_unlock_irqrestore(&ioc->diagLock, flags); | ||
| 1569 | |||
| 1570 | /* Wait a fixed amount of time for the TM pending flag to be cleared. | ||
| 1571 | * If we time out and not bus reset, then we return a FAILED status | ||
| 1572 | * to the caller. | ||
| 1573 | * The call to mptscsih_tm_pending_wait() will set the pending flag | ||
| 1574 | * if we are | ||
| 1575 | * successful. Otherwise, reload the FW. | ||
| 1576 | */ | ||
| 1577 | if (mptscsih_tm_pending_wait(hd) == FAILED) { | ||
| 1578 | if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { | ||
| 1579 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler abort: " | ||
| 1580 | "Timed out waiting for last TM (%d) to complete! \n", | ||
| 1581 | ioc->name, hd->tmPending)); | ||
| 1582 | return FAILED; | ||
| 1583 | } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { | ||
| 1584 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler target " | ||
| 1585 | "reset: Timed out waiting for last TM (%d) " | ||
| 1586 | "to complete! \n", ioc->name, | ||
| 1587 | hd->tmPending)); | ||
| 1588 | return FAILED; | ||
| 1589 | } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { | ||
| 1590 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler bus reset: " | ||
| 1591 | "Timed out waiting for last TM (%d) to complete! \n", | ||
| 1592 | ioc->name, hd->tmPending)); | ||
| 1593 | return FAILED; | ||
| 1594 | } | ||
| 1595 | } else { | ||
| 1596 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
| 1597 | hd->tmPending |= (1 << type); | ||
| 1598 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
| 1599 | } | ||
| 1600 | 1508 | ||
| 1509 | issue_hard_reset = 0; | ||
| 1601 | ioc_raw_state = mpt_GetIocState(ioc, 0); | 1510 | ioc_raw_state = mpt_GetIocState(ioc, 0); |
| 1602 | 1511 | ||
| 1603 | if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { | 1512 | if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { |
| 1604 | printk(MYIOC_s_WARN_FMT | 1513 | printk(MYIOC_s_WARN_FMT |
| 1605 | "TM Handler for type=%x: IOC Not operational (0x%x)!\n", | 1514 | "TaskMgmt type=%x: IOC Not operational (0x%x)!\n", |
| 1606 | ioc->name, type, ioc_raw_state); | 1515 | ioc->name, type, ioc_raw_state); |
| 1607 | printk(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name); | 1516 | printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n", |
| 1517 | ioc->name, __func__); | ||
| 1608 | if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) | 1518 | if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) |
| 1609 | printk(MYIOC_s_WARN_FMT "TMHandler: HardReset " | 1519 | printk(MYIOC_s_WARN_FMT "TaskMgmt HardReset " |
| 1610 | "FAILED!!\n", ioc->name); | 1520 | "FAILED!!\n", ioc->name); |
| 1611 | return FAILED; | 1521 | return 0; |
| 1612 | } | 1522 | } |
| 1613 | 1523 | ||
| 1614 | if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { | 1524 | if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { |
| 1615 | printk(MYIOC_s_WARN_FMT | 1525 | printk(MYIOC_s_WARN_FMT |
| 1616 | "TM Handler for type=%x: ioc_state: " | 1526 | "TaskMgmt type=%x: ioc_state: " |
| 1617 | "DOORBELL_ACTIVE (0x%x)!\n", | 1527 | "DOORBELL_ACTIVE (0x%x)!\n", |
| 1618 | ioc->name, type, ioc_raw_state); | 1528 | ioc->name, type, ioc_raw_state); |
| 1619 | return FAILED; | 1529 | return FAILED; |
| 1620 | } | 1530 | } |
| 1621 | 1531 | ||
| 1622 | /* Isse the Task Mgmt request. | 1532 | mutex_lock(&ioc->taskmgmt_cmds.mutex); |
| 1623 | */ | 1533 | if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { |
| 1624 | if (hd->hard_resets < -1) | 1534 | mf = NULL; |
| 1625 | hd->hard_resets++; | 1535 | retval = FAILED; |
| 1626 | 1536 | goto out; | |
| 1627 | rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, | 1537 | } |
| 1628 | ctx2abort, timeout); | ||
| 1629 | if (rc) | ||
| 1630 | printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", | ||
| 1631 | ioc->name); | ||
| 1632 | else | ||
| 1633 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n", | ||
| 1634 | ioc->name)); | ||
| 1635 | |||
| 1636 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 1637 | "TMHandler rc = %d!\n", ioc->name, rc)); | ||
| 1638 | |||
| 1639 | return rc; | ||
| 1640 | } | ||
| 1641 | |||
| 1642 | |||
| 1643 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
| 1644 | /** | ||
| 1645 | * mptscsih_IssueTaskMgmt - Generic send Task Management function. | ||
| 1646 | * @hd: Pointer to MPT_SCSI_HOST structure | ||
| 1647 | * @type: Task Management type | ||
| 1648 | * @channel: channel number for task management | ||
| 1649 | * @id: Logical Target ID for reset (if appropriate) | ||
| 1650 | * @lun: Logical Unit for reset (if appropriate) | ||
| 1651 | * @ctx2abort: Context for the task to be aborted (if appropriate) | ||
| 1652 | * @timeout: timeout for task management control | ||
| 1653 | * | ||
| 1654 | * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) | ||
| 1655 | * or a non-interrupt thread. In the former, must not call schedule(). | ||
| 1656 | * | ||
| 1657 | * Not all fields are meaningfull for all task types. | ||
| 1658 | * | ||
| 1659 | * Returns 0 for SUCCESS, or FAILED. | ||
| 1660 | * | ||
| 1661 | **/ | ||
| 1662 | static int | ||
| 1663 | mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) | ||
| 1664 | { | ||
| 1665 | MPT_FRAME_HDR *mf; | ||
| 1666 | SCSITaskMgmt_t *pScsiTm; | ||
| 1667 | int ii; | ||
| 1668 | int retval; | ||
| 1669 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 1670 | 1538 | ||
| 1671 | /* Return Fail to calling function if no message frames available. | 1539 | /* Return Fail to calling function if no message frames available. |
| 1672 | */ | 1540 | */ |
| 1673 | if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { | 1541 | if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { |
| 1674 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n", | 1542 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 1675 | ioc->name)); | 1543 | "TaskMgmt no msg frames!!\n", ioc->name)); |
| 1676 | return FAILED; | 1544 | retval = FAILED; |
| 1545 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
| 1546 | goto out; | ||
| 1677 | } | 1547 | } |
| 1678 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n", | 1548 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n", |
| 1679 | ioc->name, mf)); | 1549 | ioc->name, mf)); |
| 1680 | 1550 | ||
| 1681 | /* Format the Request | 1551 | /* Format the Request |
| @@ -1699,11 +1569,14 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i | |||
| 1699 | 1569 | ||
| 1700 | pScsiTm->TaskMsgContext = ctx2abort; | 1570 | pScsiTm->TaskMsgContext = ctx2abort; |
| 1701 | 1571 | ||
| 1702 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " | 1572 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt: ctx2abort (0x%08x) " |
| 1703 | "type=%d\n", ioc->name, ctx2abort, type)); | 1573 | "task_type = 0x%02X, timeout = %ld\n", ioc->name, ctx2abort, |
| 1574 | type, timeout)); | ||
| 1704 | 1575 | ||
| 1705 | DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm); | 1576 | DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm); |
| 1706 | 1577 | ||
| 1578 | INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status) | ||
| 1579 | time_count = jiffies; | ||
| 1707 | if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && | 1580 | if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && |
| 1708 | (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) | 1581 | (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) |
| 1709 | mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); | 1582 | mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); |
| @@ -1711,47 +1584,50 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i | |||
| 1711 | retval = mpt_send_handshake_request(ioc->TaskCtx, ioc, | 1584 | retval = mpt_send_handshake_request(ioc->TaskCtx, ioc, |
| 1712 | sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); | 1585 | sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); |
| 1713 | if (retval) { | 1586 | if (retval) { |
| 1714 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!" | 1587 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 1715 | " (hd %p, ioc %p, mf %p, rc=%d) \n", ioc->name, hd, | 1588 | "TaskMgmt handshake FAILED!(mf=%p, rc=%d) \n", |
| 1716 | ioc, mf, retval)); | 1589 | ioc->name, mf, retval)); |
| 1717 | goto fail_out; | 1590 | mpt_free_msg_frame(ioc, mf); |
| 1591 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
| 1592 | goto out; | ||
| 1718 | } | 1593 | } |
| 1719 | } | 1594 | } |
| 1720 | 1595 | ||
| 1721 | if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { | 1596 | timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, |
| 1722 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!" | 1597 | timeout*HZ); |
| 1723 | " (hd %p, ioc %p, mf %p) \n", ioc->name, hd, | 1598 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { |
| 1724 | ioc, mf)); | 1599 | retval = FAILED; |
| 1725 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n", | 1600 | dtmprintk(ioc, printk(MYIOC_s_ERR_FMT |
| 1726 | ioc->name)); | 1601 | "TaskMgmt TIMED OUT!(mf=%p)\n", ioc->name, mf)); |
| 1727 | retval = mpt_HardResetHandler(ioc, CAN_SLEEP); | 1602 | mpt_clear_taskmgmt_in_progress_flag(ioc); |
| 1728 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n", | 1603 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) |
| 1729 | ioc->name, retval)); | 1604 | goto out; |
| 1730 | goto fail_out; | 1605 | issue_hard_reset = 1; |
| 1606 | goto out; | ||
| 1731 | } | 1607 | } |
| 1732 | 1608 | ||
| 1733 | /* | 1609 | retval = mptscsih_taskmgmt_reply(ioc, type, |
| 1734 | * Handle success case, see if theres a non-zero ioc_status. | 1610 | (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply); |
| 1735 | */ | ||
| 1736 | if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS || | ||
| 1737 | hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || | ||
| 1738 | hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) | ||
| 1739 | retval = 0; | ||
| 1740 | else | ||
| 1741 | retval = FAILED; | ||
| 1742 | 1611 | ||
| 1743 | return retval; | 1612 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 1613 | "TaskMgmt completed (%d seconds)\n", | ||
| 1614 | ioc->name, jiffies_to_msecs(jiffies - time_count)/1000)); | ||
| 1744 | 1615 | ||
| 1745 | fail_out: | 1616 | out: |
| 1746 | 1617 | ||
| 1747 | /* | 1618 | CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) |
| 1748 | * Free task management mf, and corresponding tm flags | 1619 | if (issue_hard_reset) { |
| 1749 | */ | 1620 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", |
| 1750 | mpt_free_msg_frame(ioc, mf); | 1621 | ioc->name, __func__); |
| 1751 | hd->tmPending = 0; | 1622 | retval = mpt_HardResetHandler(ioc, CAN_SLEEP); |
| 1752 | hd->tmState = TM_STATE_NONE; | 1623 | mpt_free_msg_frame(ioc, mf); |
| 1753 | return FAILED; | 1624 | } |
| 1625 | |||
| 1626 | retval = (retval == 0) ? 0 : FAILED; | ||
| 1627 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | ||
| 1628 | return retval; | ||
| 1754 | } | 1629 | } |
| 1630 | EXPORT_SYMBOL(mptscsih_IssueTaskMgmt); | ||
| 1755 | 1631 | ||
| 1756 | static int | 1632 | static int |
| 1757 | mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) | 1633 | mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) |
| @@ -1838,13 +1714,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
| 1838 | goto out; | 1714 | goto out; |
| 1839 | } | 1715 | } |
| 1840 | 1716 | ||
| 1841 | if (hd->resetPending) { | 1717 | if (ioc->timeouts < -1) |
| 1842 | retval = FAILED; | 1718 | ioc->timeouts++; |
| 1843 | goto out; | ||
| 1844 | } | ||
| 1845 | |||
| 1846 | if (hd->timeouts < -1) | ||
| 1847 | hd->timeouts++; | ||
| 1848 | 1719 | ||
| 1849 | if (mpt_fwfault_debug) | 1720 | if (mpt_fwfault_debug) |
| 1850 | mpt_halt_firmware(ioc); | 1721 | mpt_halt_firmware(ioc); |
| @@ -1861,22 +1732,30 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
| 1861 | 1732 | ||
| 1862 | hd->abortSCpnt = SCpnt; | 1733 | hd->abortSCpnt = SCpnt; |
| 1863 | 1734 | ||
| 1864 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, | 1735 | retval = mptscsih_IssueTaskMgmt(hd, |
| 1865 | vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, | 1736 | MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, |
| 1866 | ctx2abort, mptscsih_get_tm_timeout(ioc)); | 1737 | vdevice->vtarget->channel, |
| 1738 | vdevice->vtarget->id, vdevice->lun, | ||
| 1739 | ctx2abort, mptscsih_get_tm_timeout(ioc)); | ||
| 1867 | 1740 | ||
| 1868 | if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx && | 1741 | if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx && |
| 1869 | SCpnt->serial_number == sn) | 1742 | SCpnt->serial_number == sn) { |
| 1743 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 1744 | "task abort: command still in active list! (sc=%p)\n", | ||
| 1745 | ioc->name, SCpnt)); | ||
| 1870 | retval = FAILED; | 1746 | retval = FAILED; |
| 1747 | } else { | ||
| 1748 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 1749 | "task abort: command cleared from active list! (sc=%p)\n", | ||
| 1750 | ioc->name, SCpnt)); | ||
| 1751 | retval = SUCCESS; | ||
| 1752 | } | ||
| 1871 | 1753 | ||
| 1872 | out: | 1754 | out: |
| 1873 | printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n", | 1755 | printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n", |
| 1874 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); | 1756 | ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), SCpnt); |
| 1875 | 1757 | ||
| 1876 | if (retval == 0) | 1758 | return retval; |
| 1877 | return SUCCESS; | ||
| 1878 | else | ||
| 1879 | return FAILED; | ||
| 1880 | } | 1759 | } |
| 1881 | 1760 | ||
| 1882 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1761 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| @@ -1909,14 +1788,9 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | |||
| 1909 | ioc->name, SCpnt); | 1788 | ioc->name, SCpnt); |
| 1910 | scsi_print_command(SCpnt); | 1789 | scsi_print_command(SCpnt); |
| 1911 | 1790 | ||
| 1912 | if (hd->resetPending) { | ||
| 1913 | retval = FAILED; | ||
| 1914 | goto out; | ||
| 1915 | } | ||
| 1916 | |||
| 1917 | vdevice = SCpnt->device->hostdata; | 1791 | vdevice = SCpnt->device->hostdata; |
| 1918 | if (!vdevice || !vdevice->vtarget) { | 1792 | if (!vdevice || !vdevice->vtarget) { |
| 1919 | retval = 0; | 1793 | retval = SUCCESS; |
| 1920 | goto out; | 1794 | goto out; |
| 1921 | } | 1795 | } |
| 1922 | 1796 | ||
| @@ -1927,9 +1801,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | |||
| 1927 | goto out; | 1801 | goto out; |
| 1928 | } | 1802 | } |
| 1929 | 1803 | ||
| 1930 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, | 1804 | retval = mptscsih_IssueTaskMgmt(hd, |
| 1931 | vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0, | 1805 | MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, |
| 1932 | mptscsih_get_tm_timeout(ioc)); | 1806 | vdevice->vtarget->channel, |
| 1807 | vdevice->vtarget->id, 0, 0, | ||
| 1808 | mptscsih_get_tm_timeout(ioc)); | ||
| 1933 | 1809 | ||
| 1934 | out: | 1810 | out: |
| 1935 | printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n", | 1811 | printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n", |
| @@ -1972,12 +1848,16 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) | |||
| 1972 | ioc->name, SCpnt); | 1848 | ioc->name, SCpnt); |
| 1973 | scsi_print_command(SCpnt); | 1849 | scsi_print_command(SCpnt); |
| 1974 | 1850 | ||
| 1975 | if (hd->timeouts < -1) | 1851 | if (ioc->timeouts < -1) |
| 1976 | hd->timeouts++; | 1852 | ioc->timeouts++; |
| 1977 | 1853 | ||
| 1978 | vdevice = SCpnt->device->hostdata; | 1854 | vdevice = SCpnt->device->hostdata; |
| 1979 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | 1855 | if (!vdevice || !vdevice->vtarget) |
| 1980 | vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc)); | 1856 | return SUCCESS; |
| 1857 | retval = mptscsih_IssueTaskMgmt(hd, | ||
| 1858 | MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | ||
| 1859 | vdevice->vtarget->channel, 0, 0, 0, | ||
| 1860 | mptscsih_get_tm_timeout(ioc)); | ||
| 1981 | 1861 | ||
| 1982 | printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n", | 1862 | printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n", |
| 1983 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); | 1863 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); |
| @@ -2001,8 +1881,9 @@ int | |||
| 2001 | mptscsih_host_reset(struct scsi_cmnd *SCpnt) | 1881 | mptscsih_host_reset(struct scsi_cmnd *SCpnt) |
| 2002 | { | 1882 | { |
| 2003 | MPT_SCSI_HOST * hd; | 1883 | MPT_SCSI_HOST * hd; |
| 2004 | int retval; | 1884 | int status = SUCCESS; |
| 2005 | MPT_ADAPTER *ioc; | 1885 | MPT_ADAPTER *ioc; |
| 1886 | int retval; | ||
| 2006 | 1887 | ||
| 2007 | /* If we can't locate the host to reset, then we failed. */ | 1888 | /* If we can't locate the host to reset, then we failed. */ |
| 2008 | if ((hd = shost_priv(SCpnt->device->host)) == NULL){ | 1889 | if ((hd = shost_priv(SCpnt->device->host)) == NULL){ |
| @@ -2021,86 +1902,71 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) | |||
| 2021 | /* If our attempts to reset the host failed, then return a failed | 1902 | /* If our attempts to reset the host failed, then return a failed |
| 2022 | * status. The host will be taken off line by the SCSI mid-layer. | 1903 | * status. The host will be taken off line by the SCSI mid-layer. |
| 2023 | */ | 1904 | */ |
| 2024 | if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) { | 1905 | retval = mpt_HardResetHandler(ioc, CAN_SLEEP); |
| 2025 | retval = FAILED; | 1906 | if (retval < 0) |
| 2026 | } else { | 1907 | status = FAILED; |
| 2027 | /* Make sure TM pending is cleared and TM state is set to | 1908 | else |
| 2028 | * NONE. | 1909 | status = SUCCESS; |
| 2029 | */ | ||
| 2030 | retval = 0; | ||
| 2031 | hd->tmPending = 0; | ||
| 2032 | hd->tmState = TM_STATE_NONE; | ||
| 2033 | } | ||
| 2034 | 1910 | ||
| 2035 | printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n", | 1911 | printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n", |
| 2036 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); | 1912 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); |
| 2037 | 1913 | ||
| 2038 | return retval; | 1914 | return status; |
| 2039 | } | 1915 | } |
| 2040 | 1916 | ||
| 2041 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
| 2042 | /** | ||
| 2043 | * mptscsih_tm_pending_wait - wait for pending task management request to complete | ||
| 2044 | * @hd: Pointer to MPT host structure. | ||
| 2045 | * | ||
| 2046 | * Returns {SUCCESS,FAILED}. | ||
| 2047 | */ | ||
| 2048 | static int | 1917 | static int |
| 2049 | mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) | 1918 | mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type, |
| 1919 | SCSITaskMgmtReply_t *pScsiTmReply) | ||
| 2050 | { | 1920 | { |
| 2051 | unsigned long flags; | 1921 | u16 iocstatus; |
| 2052 | int loop_count = 4 * 10; /* Wait 10 seconds */ | 1922 | u32 termination_count; |
| 2053 | int status = FAILED; | 1923 | int retval; |
| 2054 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 2055 | 1924 | ||
| 2056 | do { | 1925 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { |
| 2057 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 1926 | retval = FAILED; |
| 2058 | if (hd->tmState == TM_STATE_NONE) { | 1927 | goto out; |
| 2059 | hd->tmState = TM_STATE_IN_PROGRESS; | 1928 | } |
| 2060 | hd->tmPending = 1; | ||
| 2061 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
| 2062 | status = SUCCESS; | ||
| 2063 | break; | ||
| 2064 | } | ||
| 2065 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
| 2066 | msleep(250); | ||
| 2067 | } while (--loop_count); | ||
| 2068 | 1929 | ||
| 2069 | return status; | 1930 | DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply); |
| 2070 | } | ||
| 2071 | 1931 | ||
| 2072 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1932 | iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; |
| 2073 | /** | 1933 | termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); |
| 2074 | * mptscsih_tm_wait_for_completion - wait for completion of TM task | ||
| 2075 | * @hd: Pointer to MPT host structure. | ||
| 2076 | * @timeout: timeout value | ||
| 2077 | * | ||
| 2078 | * Returns {SUCCESS,FAILED}. | ||
| 2079 | */ | ||
| 2080 | static int | ||
| 2081 | mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ) | ||
| 2082 | { | ||
| 2083 | unsigned long flags; | ||
| 2084 | int loop_count = 4 * timeout; | ||
| 2085 | int status = FAILED; | ||
| 2086 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 2087 | 1934 | ||
| 2088 | do { | 1935 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2089 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 1936 | "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n" |
| 2090 | if(hd->tmPending == 0) { | 1937 | "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n" |
| 2091 | status = SUCCESS; | 1938 | "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus, |
| 2092 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 1939 | pScsiTmReply->TargetID, type, le16_to_cpu(pScsiTmReply->IOCStatus), |
| 2093 | break; | 1940 | le32_to_cpu(pScsiTmReply->IOCLogInfo), pScsiTmReply->ResponseCode, |
| 2094 | } | 1941 | termination_count)); |
| 2095 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
| 2096 | msleep(250); | ||
| 2097 | } while (--loop_count); | ||
| 2098 | 1942 | ||
| 2099 | return status; | 1943 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && |
| 1944 | pScsiTmReply->ResponseCode) | ||
| 1945 | mptscsih_taskmgmt_response_code(ioc, | ||
| 1946 | pScsiTmReply->ResponseCode); | ||
| 1947 | |||
| 1948 | if (iocstatus == MPI_IOCSTATUS_SUCCESS) { | ||
| 1949 | retval = 0; | ||
| 1950 | goto out; | ||
| 1951 | } | ||
| 1952 | |||
| 1953 | retval = FAILED; | ||
| 1954 | if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { | ||
| 1955 | if (termination_count == 1) | ||
| 1956 | retval = 0; | ||
| 1957 | goto out; | ||
| 1958 | } | ||
| 1959 | |||
| 1960 | if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || | ||
| 1961 | iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) | ||
| 1962 | retval = 0; | ||
| 1963 | |||
| 1964 | out: | ||
| 1965 | return retval; | ||
| 2100 | } | 1966 | } |
| 2101 | 1967 | ||
| 2102 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1968 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 2103 | static void | 1969 | void |
| 2104 | mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) | 1970 | mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) |
| 2105 | { | 1971 | { |
| 2106 | char *desc; | 1972 | char *desc; |
| @@ -2134,6 +2000,7 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) | |||
| 2134 | printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n", | 2000 | printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n", |
| 2135 | ioc->name, response_code, desc); | 2001 | ioc->name, response_code, desc); |
| 2136 | } | 2002 | } |
| 2003 | EXPORT_SYMBOL(mptscsih_taskmgmt_response_code); | ||
| 2137 | 2004 | ||
| 2138 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2005 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 2139 | /** | 2006 | /** |
| @@ -2150,97 +2017,28 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) | |||
| 2150 | * Returns 1 indicating alloc'd request frame ptr should be freed. | 2017 | * Returns 1 indicating alloc'd request frame ptr should be freed. |
| 2151 | **/ | 2018 | **/ |
| 2152 | int | 2019 | int |
| 2153 | mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | 2020 | mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, |
| 2021 | MPT_FRAME_HDR *mr) | ||
| 2154 | { | 2022 | { |
| 2155 | SCSITaskMgmtReply_t *pScsiTmReply; | 2023 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2156 | SCSITaskMgmt_t *pScsiTmReq; | 2024 | "TaskMgmt completed (mf=%p, mr=%p)\n", ioc->name, mf, mr)); |
| 2157 | MPT_SCSI_HOST *hd; | ||
| 2158 | unsigned long flags; | ||
| 2159 | u16 iocstatus; | ||
| 2160 | u8 tmType; | ||
| 2161 | u32 termination_count; | ||
| 2162 | |||
| 2163 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", | ||
| 2164 | ioc->name, mf, mr)); | ||
| 2165 | if (!ioc->sh) { | ||
| 2166 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT | ||
| 2167 | "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); | ||
| 2168 | return 1; | ||
| 2169 | } | ||
| 2170 | |||
| 2171 | if (mr == NULL) { | ||
| 2172 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT | ||
| 2173 | "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf)); | ||
| 2174 | return 1; | ||
| 2175 | } | ||
| 2176 | |||
| 2177 | hd = shost_priv(ioc->sh); | ||
| 2178 | pScsiTmReply = (SCSITaskMgmtReply_t*)mr; | ||
| 2179 | pScsiTmReq = (SCSITaskMgmt_t*)mf; | ||
| 2180 | tmType = pScsiTmReq->TaskType; | ||
| 2181 | iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
| 2182 | termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); | ||
| 2183 | 2025 | ||
| 2184 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && | 2026 | ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; |
| 2185 | pScsiTmReply->ResponseCode) | ||
| 2186 | mptscsih_taskmgmt_response_code(ioc, | ||
| 2187 | pScsiTmReply->ResponseCode); | ||
| 2188 | DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply); | ||
| 2189 | 2027 | ||
| 2190 | #ifdef CONFIG_FUSION_LOGGING | 2028 | if (!mr) |
| 2191 | if ((ioc->debug_level & MPT_DEBUG_REPLY) || | ||
| 2192 | (ioc->debug_level & MPT_DEBUG_TM )) | ||
| 2193 | printk("%s: ha=%d [%d:%d:0] task_type=0x%02X " | ||
| 2194 | "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X " | ||
| 2195 | "term_cmnds=%d\n", __func__, ioc->id, pScsiTmReply->Bus, | ||
| 2196 | pScsiTmReply->TargetID, pScsiTmReq->TaskType, | ||
| 2197 | le16_to_cpu(pScsiTmReply->IOCStatus), | ||
| 2198 | le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode, | ||
| 2199 | le32_to_cpu(pScsiTmReply->TerminationCount)); | ||
| 2200 | #endif | ||
| 2201 | if (!iocstatus) { | ||
| 2202 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name)); | ||
| 2203 | hd->abortSCpnt = NULL; | ||
| 2204 | goto out; | 2029 | goto out; |
| 2205 | } | ||
| 2206 | |||
| 2207 | /* Error? (anything non-zero?) */ | ||
| 2208 | |||
| 2209 | /* clear flags and continue. | ||
| 2210 | */ | ||
| 2211 | switch (tmType) { | ||
| 2212 | |||
| 2213 | case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK: | ||
| 2214 | if (termination_count == 1) | ||
| 2215 | iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED; | ||
| 2216 | hd->abortSCpnt = NULL; | ||
| 2217 | break; | ||
| 2218 | |||
| 2219 | case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS: | ||
| 2220 | |||
| 2221 | /* If an internal command is present | ||
| 2222 | * or the TM failed - reload the FW. | ||
| 2223 | * FC FW may respond FAILED to an ABORT | ||
| 2224 | */ | ||
| 2225 | if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED || | ||
| 2226 | hd->cmdPtr) | ||
| 2227 | if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) | ||
| 2228 | printk(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name); | ||
| 2229 | break; | ||
| 2230 | |||
| 2231 | case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: | ||
| 2232 | default: | ||
| 2233 | break; | ||
| 2234 | } | ||
| 2235 | 2030 | ||
| 2031 | ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID; | ||
| 2032 | memcpy(ioc->taskmgmt_cmds.reply, mr, | ||
| 2033 | min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength)); | ||
| 2236 | out: | 2034 | out: |
| 2237 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 2035 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) { |
| 2238 | hd->tmPending = 0; | 2036 | mpt_clear_taskmgmt_in_progress_flag(ioc); |
| 2239 | hd->tmState = TM_STATE_NONE; | 2037 | ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING; |
| 2240 | hd->tm_iocstatus = iocstatus; | 2038 | complete(&ioc->taskmgmt_cmds.done); |
| 2241 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 2039 | return 1; |
| 2242 | 2040 | } | |
| 2243 | return 1; | 2041 | return 0; |
| 2244 | } | 2042 | } |
| 2245 | 2043 | ||
| 2246 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2044 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| @@ -2290,8 +2088,10 @@ int | |||
| 2290 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) | 2088 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) |
| 2291 | { | 2089 | { |
| 2292 | struct inactive_raid_component_info *component_info; | 2090 | struct inactive_raid_component_info *component_info; |
| 2293 | int i; | 2091 | int i, j; |
| 2092 | RaidPhysDiskPage1_t *phys_disk; | ||
| 2294 | int rc = 0; | 2093 | int rc = 0; |
| 2094 | int num_paths; | ||
| 2295 | 2095 | ||
| 2296 | if (!ioc->raid_data.pIocPg3) | 2096 | if (!ioc->raid_data.pIocPg3) |
| 2297 | goto out; | 2097 | goto out; |
| @@ -2303,6 +2103,45 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 2303 | } | 2103 | } |
| 2304 | } | 2104 | } |
| 2305 | 2105 | ||
| 2106 | if (ioc->bus_type != SAS) | ||
| 2107 | goto out; | ||
| 2108 | |||
| 2109 | /* | ||
| 2110 | * Check if dual path | ||
| 2111 | */ | ||
| 2112 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
| 2113 | num_paths = mpt_raid_phys_disk_get_num_paths(ioc, | ||
| 2114 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); | ||
| 2115 | if (num_paths < 2) | ||
| 2116 | continue; | ||
| 2117 | phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + | ||
| 2118 | (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); | ||
| 2119 | if (!phys_disk) | ||
| 2120 | continue; | ||
| 2121 | if ((mpt_raid_phys_disk_pg1(ioc, | ||
| 2122 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, | ||
| 2123 | phys_disk))) { | ||
| 2124 | kfree(phys_disk); | ||
| 2125 | continue; | ||
| 2126 | } | ||
| 2127 | for (j = 0; j < num_paths; j++) { | ||
| 2128 | if ((phys_disk->Path[j].Flags & | ||
| 2129 | MPI_RAID_PHYSDISK1_FLAG_INVALID)) | ||
| 2130 | continue; | ||
| 2131 | if ((phys_disk->Path[j].Flags & | ||
| 2132 | MPI_RAID_PHYSDISK1_FLAG_BROKEN)) | ||
| 2133 | continue; | ||
| 2134 | if ((id == phys_disk->Path[j].PhysDiskID) && | ||
| 2135 | (channel == phys_disk->Path[j].PhysDiskBus)) { | ||
| 2136 | rc = 1; | ||
| 2137 | kfree(phys_disk); | ||
| 2138 | goto out; | ||
| 2139 | } | ||
| 2140 | } | ||
| 2141 | kfree(phys_disk); | ||
| 2142 | } | ||
| 2143 | |||
| 2144 | |||
| 2306 | /* | 2145 | /* |
| 2307 | * Check inactive list for matching phys disks | 2146 | * Check inactive list for matching phys disks |
| 2308 | */ | 2147 | */ |
| @@ -2327,8 +2166,10 @@ u8 | |||
| 2327 | mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | 2166 | mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) |
| 2328 | { | 2167 | { |
| 2329 | struct inactive_raid_component_info *component_info; | 2168 | struct inactive_raid_component_info *component_info; |
| 2330 | int i; | 2169 | int i, j; |
| 2170 | RaidPhysDiskPage1_t *phys_disk; | ||
| 2331 | int rc = -ENXIO; | 2171 | int rc = -ENXIO; |
| 2172 | int num_paths; | ||
| 2332 | 2173 | ||
| 2333 | if (!ioc->raid_data.pIocPg3) | 2174 | if (!ioc->raid_data.pIocPg3) |
| 2334 | goto out; | 2175 | goto out; |
| @@ -2340,6 +2181,44 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 2340 | } | 2181 | } |
| 2341 | } | 2182 | } |
| 2342 | 2183 | ||
| 2184 | if (ioc->bus_type != SAS) | ||
| 2185 | goto out; | ||
| 2186 | |||
| 2187 | /* | ||
| 2188 | * Check if dual path | ||
| 2189 | */ | ||
| 2190 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
| 2191 | num_paths = mpt_raid_phys_disk_get_num_paths(ioc, | ||
| 2192 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); | ||
| 2193 | if (num_paths < 2) | ||
| 2194 | continue; | ||
| 2195 | phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + | ||
| 2196 | (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); | ||
| 2197 | if (!phys_disk) | ||
| 2198 | continue; | ||
| 2199 | if ((mpt_raid_phys_disk_pg1(ioc, | ||
| 2200 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, | ||
| 2201 | phys_disk))) { | ||
| 2202 | kfree(phys_disk); | ||
| 2203 | continue; | ||
| 2204 | } | ||
| 2205 | for (j = 0; j < num_paths; j++) { | ||
| 2206 | if ((phys_disk->Path[j].Flags & | ||
| 2207 | MPI_RAID_PHYSDISK1_FLAG_INVALID)) | ||
| 2208 | continue; | ||
| 2209 | if ((phys_disk->Path[j].Flags & | ||
| 2210 | MPI_RAID_PHYSDISK1_FLAG_BROKEN)) | ||
| 2211 | continue; | ||
| 2212 | if ((id == phys_disk->Path[j].PhysDiskID) && | ||
| 2213 | (channel == phys_disk->Path[j].PhysDiskBus)) { | ||
| 2214 | rc = phys_disk->PhysDiskNum; | ||
| 2215 | kfree(phys_disk); | ||
| 2216 | goto out; | ||
| 2217 | } | ||
| 2218 | } | ||
| 2219 | kfree(phys_disk); | ||
| 2220 | } | ||
| 2221 | |||
| 2343 | /* | 2222 | /* |
| 2344 | * Check inactive list for matching phys disks | 2223 | * Check inactive list for matching phys disks |
| 2345 | */ | 2224 | */ |
| @@ -2457,7 +2336,6 @@ mptscsih_slave_configure(struct scsi_device *sdev) | |||
| 2457 | sdev->ppr, sdev->inquiry_len)); | 2336 | sdev->ppr, sdev->inquiry_len)); |
| 2458 | 2337 | ||
| 2459 | vdevice->configured_lun = 1; | 2338 | vdevice->configured_lun = 1; |
| 2460 | mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); | ||
| 2461 | 2339 | ||
| 2462 | dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 2340 | dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2463 | "Queue depth=%d, tflags=%x\n", | 2341 | "Queue depth=%d, tflags=%x\n", |
| @@ -2469,6 +2347,7 @@ mptscsih_slave_configure(struct scsi_device *sdev) | |||
| 2469 | ioc->name, vtarget->negoFlags, vtarget->maxOffset, | 2347 | ioc->name, vtarget->negoFlags, vtarget->maxOffset, |
| 2470 | vtarget->minSyncFactor)); | 2348 | vtarget->minSyncFactor)); |
| 2471 | 2349 | ||
| 2350 | mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); | ||
| 2472 | dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 2351 | dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2473 | "tagged %d, simple %d, ordered %d\n", | 2352 | "tagged %d, simple %d, ordered %d\n", |
| 2474 | ioc->name,sdev->tagged_supported, sdev->simple_tags, | 2353 | ioc->name,sdev->tagged_supported, sdev->simple_tags, |
| @@ -2542,15 +2421,13 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR | |||
| 2542 | } | 2421 | } |
| 2543 | 2422 | ||
| 2544 | /** | 2423 | /** |
| 2545 | * mptscsih_get_scsi_lookup | 2424 | * mptscsih_get_scsi_lookup - retrieves scmd entry |
| 2546 | * @ioc: Pointer to MPT_ADAPTER structure | 2425 | * @ioc: Pointer to MPT_ADAPTER structure |
| 2547 | * @i: index into the array | 2426 | * @i: index into the array |
| 2548 | * | 2427 | * |
| 2549 | * retrieves scmd entry from ScsiLookup[] array list | ||
| 2550 | * | ||
| 2551 | * Returns the scsi_cmd pointer | 2428 | * Returns the scsi_cmd pointer |
| 2552 | **/ | 2429 | */ |
| 2553 | static struct scsi_cmnd * | 2430 | struct scsi_cmnd * |
| 2554 | mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i) | 2431 | mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i) |
| 2555 | { | 2432 | { |
| 2556 | unsigned long flags; | 2433 | unsigned long flags; |
| @@ -2562,15 +2439,15 @@ mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i) | |||
| 2562 | 2439 | ||
| 2563 | return scmd; | 2440 | return scmd; |
| 2564 | } | 2441 | } |
| 2442 | EXPORT_SYMBOL(mptscsih_get_scsi_lookup); | ||
| 2565 | 2443 | ||
| 2566 | /** | 2444 | /** |
| 2567 | * mptscsih_getclear_scsi_lookup | 2445 | * mptscsih_getclear_scsi_lookup - retrieves and clears scmd entry from ScsiLookup[] array list |
| 2568 | * @ioc: Pointer to MPT_ADAPTER structure | 2446 | * @ioc: Pointer to MPT_ADAPTER structure |
| 2569 | * @i: index into the array | 2447 | * @i: index into the array |
| 2570 | * | 2448 | * |
| 2571 | * retrieves and clears scmd entry from ScsiLookup[] array list | ||
| 2572 | * | ||
| 2573 | * Returns the scsi_cmd pointer | 2449 | * Returns the scsi_cmd pointer |
| 2450 | * | ||
| 2574 | **/ | 2451 | **/ |
| 2575 | static struct scsi_cmnd * | 2452 | static struct scsi_cmnd * |
| 2576 | mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i) | 2453 | mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i) |
| @@ -2635,94 +2512,33 @@ int | |||
| 2635 | mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | 2512 | mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) |
| 2636 | { | 2513 | { |
| 2637 | MPT_SCSI_HOST *hd; | 2514 | MPT_SCSI_HOST *hd; |
| 2638 | unsigned long flags; | ||
| 2639 | 2515 | ||
| 2640 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 2641 | ": IOC %s_reset routed to SCSI host driver!\n", | ||
| 2642 | ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( | ||
| 2643 | reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); | ||
| 2644 | |||
| 2645 | /* If a FW reload request arrives after base installed but | ||
| 2646 | * before all scsi hosts have been attached, then an alt_ioc | ||
| 2647 | * may have a NULL sh pointer. | ||
| 2648 | */ | ||
| 2649 | if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL) | 2516 | if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL) |
| 2650 | return 0; | 2517 | return 0; |
| 2651 | else | ||
| 2652 | hd = shost_priv(ioc->sh); | ||
| 2653 | |||
| 2654 | if (reset_phase == MPT_IOC_SETUP_RESET) { | ||
| 2655 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name)); | ||
| 2656 | |||
| 2657 | /* Clean Up: | ||
| 2658 | * 1. Set Hard Reset Pending Flag | ||
| 2659 | * All new commands go to doneQ | ||
| 2660 | */ | ||
| 2661 | hd->resetPending = 1; | ||
| 2662 | |||
| 2663 | } else if (reset_phase == MPT_IOC_PRE_RESET) { | ||
| 2664 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Diag Reset\n", ioc->name)); | ||
| 2665 | 2518 | ||
| 2666 | /* 2. Flush running commands | 2519 | hd = shost_priv(ioc->sh); |
| 2667 | * Clean ScsiLookup (and associated memory) | 2520 | switch (reset_phase) { |
| 2668 | * AND clean mytaskQ | 2521 | case MPT_IOC_SETUP_RESET: |
| 2669 | */ | 2522 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2670 | 2523 | "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__)); | |
| 2671 | /* 2b. Reply to OS all known outstanding I/O commands. | 2524 | break; |
| 2672 | */ | 2525 | case MPT_IOC_PRE_RESET: |
| 2526 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 2527 | "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__)); | ||
| 2673 | mptscsih_flush_running_cmds(hd); | 2528 | mptscsih_flush_running_cmds(hd); |
| 2674 | 2529 | break; | |
| 2675 | /* 2c. If there was an internal command that | 2530 | case MPT_IOC_POST_RESET: |
| 2676 | * has not completed, configuration or io request, | 2531 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2677 | * free these resources. | 2532 | "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__)); |
| 2678 | */ | 2533 | if (ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING) { |
| 2679 | if (hd->cmdPtr) { | 2534 | ioc->internal_cmds.status |= |
| 2680 | del_timer(&hd->timer); | 2535 | MPT_MGMT_STATUS_DID_IOCRESET; |
| 2681 | mpt_free_msg_frame(ioc, hd->cmdPtr); | 2536 | complete(&ioc->internal_cmds.done); |
| 2682 | } | ||
| 2683 | |||
| 2684 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Reset complete.\n", ioc->name)); | ||
| 2685 | |||
| 2686 | } else { | ||
| 2687 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Diag Reset\n", ioc->name)); | ||
| 2688 | |||
| 2689 | /* Once a FW reload begins, all new OS commands are | ||
| 2690 | * redirected to the doneQ w/ a reset status. | ||
| 2691 | * Init all control structures. | ||
| 2692 | */ | ||
| 2693 | |||
| 2694 | /* 2. Chain Buffer initialization | ||
| 2695 | */ | ||
| 2696 | |||
| 2697 | /* 4. Renegotiate to all devices, if SPI | ||
| 2698 | */ | ||
| 2699 | |||
| 2700 | /* 5. Enable new commands to be posted | ||
| 2701 | */ | ||
| 2702 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
| 2703 | hd->tmPending = 0; | ||
| 2704 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
| 2705 | hd->resetPending = 0; | ||
| 2706 | hd->tmState = TM_STATE_NONE; | ||
| 2707 | |||
| 2708 | /* 6. If there was an internal command, | ||
| 2709 | * wake this process up. | ||
| 2710 | */ | ||
| 2711 | if (hd->cmdPtr) { | ||
| 2712 | /* | ||
| 2713 | * Wake up the original calling thread | ||
| 2714 | */ | ||
| 2715 | hd->pLocal = &hd->localReply; | ||
| 2716 | hd->pLocal->completion = MPT_SCANDV_DID_RESET; | ||
| 2717 | hd->scandv_wait_done = 1; | ||
| 2718 | wake_up(&hd->scandv_waitq); | ||
| 2719 | hd->cmdPtr = NULL; | ||
| 2720 | } | 2537 | } |
| 2721 | 2538 | break; | |
| 2722 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Reset complete.\n", ioc->name)); | 2539 | default: |
| 2723 | 2540 | break; | |
| 2724 | } | 2541 | } |
| 2725 | |||
| 2726 | return 1; /* currently means nothing really */ | 2542 | return 1; /* currently means nothing really */ |
| 2727 | } | 2543 | } |
| 2728 | 2544 | ||
| @@ -2730,55 +2546,16 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
| 2730 | int | 2546 | int |
| 2731 | mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | 2547 | mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) |
| 2732 | { | 2548 | { |
| 2733 | MPT_SCSI_HOST *hd; | ||
| 2734 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; | 2549 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; |
| 2735 | 2550 | ||
| 2736 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", | 2551 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2737 | ioc->name, event)); | 2552 | "MPT event (=%02Xh) routed to SCSI host driver!\n", |
| 2738 | 2553 | ioc->name, event)); | |
| 2739 | if (ioc->sh == NULL || | ||
| 2740 | ((hd = shost_priv(ioc->sh)) == NULL)) | ||
| 2741 | return 1; | ||
| 2742 | |||
| 2743 | switch (event) { | ||
| 2744 | case MPI_EVENT_UNIT_ATTENTION: /* 03 */ | ||
| 2745 | /* FIXME! */ | ||
| 2746 | break; | ||
| 2747 | case MPI_EVENT_IOC_BUS_RESET: /* 04 */ | ||
| 2748 | case MPI_EVENT_EXT_BUS_RESET: /* 05 */ | ||
| 2749 | if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1)) | ||
| 2750 | hd->soft_resets++; | ||
| 2751 | break; | ||
| 2752 | case MPI_EVENT_LOGOUT: /* 09 */ | ||
| 2753 | /* FIXME! */ | ||
| 2754 | break; | ||
| 2755 | |||
| 2756 | case MPI_EVENT_RESCAN: /* 06 */ | ||
| 2757 | break; | ||
| 2758 | |||
| 2759 | /* | ||
| 2760 | * CHECKME! Don't think we need to do | ||
| 2761 | * anything for these, but... | ||
| 2762 | */ | ||
| 2763 | case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ | ||
| 2764 | case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ | ||
| 2765 | /* | ||
| 2766 | * CHECKME! Falling thru... | ||
| 2767 | */ | ||
| 2768 | break; | ||
| 2769 | |||
| 2770 | case MPI_EVENT_INTEGRATED_RAID: /* 0B */ | ||
| 2771 | break; | ||
| 2772 | 2554 | ||
| 2773 | case MPI_EVENT_NONE: /* 00 */ | 2555 | if ((event == MPI_EVENT_IOC_BUS_RESET || |
| 2774 | case MPI_EVENT_LOG_DATA: /* 01 */ | 2556 | event == MPI_EVENT_EXT_BUS_RESET) && |
| 2775 | case MPI_EVENT_STATE_CHANGE: /* 02 */ | 2557 | (ioc->bus_type == SPI) && (ioc->soft_resets < -1)) |
| 2776 | case MPI_EVENT_EVENT_CHANGE: /* 0A */ | 2558 | ioc->soft_resets++; |
| 2777 | default: | ||
| 2778 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": Ignoring event (=%02Xh)\n", | ||
| 2779 | ioc->name, event)); | ||
| 2780 | break; | ||
| 2781 | } | ||
| 2782 | 2559 | ||
| 2783 | return 1; /* currently means nothing really */ | 2560 | return 1; /* currently means nothing really */ |
| 2784 | } | 2561 | } |
| @@ -2809,153 +2586,44 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
| 2809 | * Used ONLY for DV and other internal commands. | 2586 | * Used ONLY for DV and other internal commands. |
| 2810 | */ | 2587 | */ |
| 2811 | int | 2588 | int |
| 2812 | mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | 2589 | mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, |
| 2590 | MPT_FRAME_HDR *reply) | ||
| 2813 | { | 2591 | { |
| 2814 | MPT_SCSI_HOST *hd; | ||
| 2815 | SCSIIORequest_t *pReq; | 2592 | SCSIIORequest_t *pReq; |
| 2816 | int completionCode; | 2593 | SCSIIOReply_t *pReply; |
| 2594 | u8 cmd; | ||
| 2817 | u16 req_idx; | 2595 | u16 req_idx; |
| 2596 | u8 *sense_data; | ||
| 2597 | int sz; | ||
| 2818 | 2598 | ||
| 2819 | hd = shost_priv(ioc->sh); | 2599 | ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; |
| 2820 | 2600 | ioc->internal_cmds.completion_code = MPT_SCANDV_GOOD; | |
| 2821 | if ((mf == NULL) || | 2601 | if (!reply) |
| 2822 | (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { | 2602 | goto out; |
| 2823 | printk(MYIOC_s_ERR_FMT | ||
| 2824 | "ScanDvComplete, %s req frame ptr! (=%p)\n", | ||
| 2825 | ioc->name, mf?"BAD":"NULL", (void *) mf); | ||
| 2826 | goto wakeup; | ||
| 2827 | } | ||
| 2828 | |||
| 2829 | del_timer(&hd->timer); | ||
| 2830 | req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); | ||
| 2831 | mptscsih_set_scsi_lookup(ioc, req_idx, NULL); | ||
| 2832 | pReq = (SCSIIORequest_t *) mf; | ||
| 2833 | 2603 | ||
| 2834 | if (mf != hd->cmdPtr) { | 2604 | pReply = (SCSIIOReply_t *) reply; |
| 2835 | printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n", | 2605 | pReq = (SCSIIORequest_t *) req; |
| 2836 | ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx); | 2606 | ioc->internal_cmds.completion_code = |
| 2607 | mptscsih_get_completion_code(ioc, req, reply); | ||
| 2608 | ioc->internal_cmds.status |= MPT_MGMT_STATUS_RF_VALID; | ||
| 2609 | memcpy(ioc->internal_cmds.reply, reply, | ||
| 2610 | min(MPT_DEFAULT_FRAME_SIZE, 4 * reply->u.reply.MsgLength)); | ||
| 2611 | cmd = reply->u.hdr.Function; | ||
| 2612 | if (((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || | ||
| 2613 | (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) && | ||
| 2614 | (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)) { | ||
| 2615 | req_idx = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx); | ||
| 2616 | sense_data = ((u8 *)ioc->sense_buf_pool + | ||
| 2617 | (req_idx * MPT_SENSE_BUFFER_ALLOC)); | ||
| 2618 | sz = min_t(int, pReq->SenseBufferLength, | ||
| 2619 | MPT_SENSE_BUFFER_ALLOC); | ||
| 2620 | memcpy(ioc->internal_cmds.sense, sense_data, sz); | ||
| 2837 | } | 2621 | } |
| 2838 | hd->cmdPtr = NULL; | 2622 | out: |
| 2839 | 2623 | if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING)) | |
| 2840 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n", | 2624 | return 0; |
| 2841 | ioc->name, mf, mr, req_idx)); | 2625 | ioc->internal_cmds.status &= ~MPT_MGMT_STATUS_PENDING; |
| 2842 | 2626 | complete(&ioc->internal_cmds.done); | |
| 2843 | hd->pLocal = &hd->localReply; | ||
| 2844 | hd->pLocal->scsiStatus = 0; | ||
| 2845 | |||
| 2846 | /* If target struct exists, clear sense valid flag. | ||
| 2847 | */ | ||
| 2848 | if (mr == NULL) { | ||
| 2849 | completionCode = MPT_SCANDV_GOOD; | ||
| 2850 | } else { | ||
| 2851 | SCSIIOReply_t *pReply; | ||
| 2852 | u16 status; | ||
| 2853 | u8 scsi_status; | ||
| 2854 | |||
| 2855 | pReply = (SCSIIOReply_t *) mr; | ||
| 2856 | |||
| 2857 | status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
| 2858 | scsi_status = pReply->SCSIStatus; | ||
| 2859 | |||
| 2860 | |||
| 2861 | switch(status) { | ||
| 2862 | |||
| 2863 | case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ | ||
| 2864 | completionCode = MPT_SCANDV_SELECTION_TIMEOUT; | ||
| 2865 | break; | ||
| 2866 | |||
| 2867 | case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ | ||
| 2868 | case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ | ||
| 2869 | case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ | ||
| 2870 | case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ | ||
| 2871 | completionCode = MPT_SCANDV_DID_RESET; | ||
| 2872 | break; | ||
| 2873 | |||
| 2874 | case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ | ||
| 2875 | case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ | ||
| 2876 | case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ | ||
| 2877 | if (pReply->Function == MPI_FUNCTION_CONFIG) { | ||
| 2878 | ConfigReply_t *pr = (ConfigReply_t *)mr; | ||
| 2879 | completionCode = MPT_SCANDV_GOOD; | ||
| 2880 | hd->pLocal->header.PageVersion = pr->Header.PageVersion; | ||
| 2881 | hd->pLocal->header.PageLength = pr->Header.PageLength; | ||
| 2882 | hd->pLocal->header.PageNumber = pr->Header.PageNumber; | ||
| 2883 | hd->pLocal->header.PageType = pr->Header.PageType; | ||
| 2884 | |||
| 2885 | } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) { | ||
| 2886 | /* If the RAID Volume request is successful, | ||
| 2887 | * return GOOD, else indicate that | ||
| 2888 | * some type of error occurred. | ||
| 2889 | */ | ||
| 2890 | MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr; | ||
| 2891 | if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS) | ||
| 2892 | completionCode = MPT_SCANDV_GOOD; | ||
| 2893 | else | ||
| 2894 | completionCode = MPT_SCANDV_SOME_ERROR; | ||
| 2895 | memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense)); | ||
| 2896 | |||
| 2897 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { | ||
| 2898 | u8 *sense_data; | ||
| 2899 | int sz; | ||
| 2900 | |||
| 2901 | /* save sense data in global structure | ||
| 2902 | */ | ||
| 2903 | completionCode = MPT_SCANDV_SENSE; | ||
| 2904 | hd->pLocal->scsiStatus = scsi_status; | ||
| 2905 | sense_data = ((u8 *)ioc->sense_buf_pool + | ||
| 2906 | (req_idx * MPT_SENSE_BUFFER_ALLOC)); | ||
| 2907 | |||
| 2908 | sz = min_t(int, pReq->SenseBufferLength, | ||
| 2909 | SCSI_STD_SENSE_BYTES); | ||
| 2910 | memcpy(hd->pLocal->sense, sense_data, sz); | ||
| 2911 | |||
| 2912 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Check Condition, sense ptr %p\n", | ||
| 2913 | ioc->name, sense_data)); | ||
| 2914 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { | ||
| 2915 | if (pReq->CDB[0] == INQUIRY) | ||
| 2916 | completionCode = MPT_SCANDV_ISSUE_SENSE; | ||
| 2917 | else | ||
| 2918 | completionCode = MPT_SCANDV_DID_RESET; | ||
| 2919 | } | ||
| 2920 | else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) | ||
| 2921 | completionCode = MPT_SCANDV_DID_RESET; | ||
| 2922 | else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
| 2923 | completionCode = MPT_SCANDV_DID_RESET; | ||
| 2924 | else { | ||
| 2925 | completionCode = MPT_SCANDV_GOOD; | ||
| 2926 | hd->pLocal->scsiStatus = scsi_status; | ||
| 2927 | } | ||
| 2928 | break; | ||
| 2929 | |||
| 2930 | case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ | ||
| 2931 | if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
| 2932 | completionCode = MPT_SCANDV_DID_RESET; | ||
| 2933 | else | ||
| 2934 | completionCode = MPT_SCANDV_SOME_ERROR; | ||
| 2935 | break; | ||
| 2936 | |||
| 2937 | default: | ||
| 2938 | completionCode = MPT_SCANDV_SOME_ERROR; | ||
| 2939 | break; | ||
| 2940 | |||
| 2941 | } /* switch(status) */ | ||
| 2942 | |||
| 2943 | } /* end of address reply case */ | ||
| 2944 | |||
| 2945 | hd->pLocal->completion = completionCode; | ||
| 2946 | |||
| 2947 | /* MF and RF are freed in mpt_interrupt | ||
| 2948 | */ | ||
| 2949 | wakeup: | ||
| 2950 | /* Free Chain buffers (will never chain) in scan or dv */ | ||
| 2951 | //mptscsih_freeChainBuffers(ioc, req_idx); | ||
| 2952 | |||
| 2953 | /* | ||
| 2954 | * Wake up the original calling thread | ||
| 2955 | */ | ||
| 2956 | hd->scandv_wait_done = 1; | ||
| 2957 | wake_up(&hd->scandv_waitq); | ||
| 2958 | |||
| 2959 | return 1; | 2627 | return 1; |
| 2960 | } | 2628 | } |
| 2961 | 2629 | ||
| @@ -3004,6 +2672,95 @@ mptscsih_timer_expired(unsigned long data) | |||
| 3004 | return; | 2672 | return; |
| 3005 | } | 2673 | } |
| 3006 | 2674 | ||
| 2675 | /** | ||
| 2676 | * mptscsih_get_completion_code - | ||
| 2677 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 2678 | * @reply: | ||
| 2679 | * @cmd: | ||
| 2680 | * | ||
| 2681 | **/ | ||
| 2682 | static int | ||
| 2683 | mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, | ||
| 2684 | MPT_FRAME_HDR *reply) | ||
| 2685 | { | ||
| 2686 | SCSIIOReply_t *pReply; | ||
| 2687 | MpiRaidActionReply_t *pr; | ||
| 2688 | u8 scsi_status; | ||
| 2689 | u16 status; | ||
| 2690 | int completion_code; | ||
| 2691 | |||
| 2692 | pReply = (SCSIIOReply_t *)reply; | ||
| 2693 | status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
| 2694 | scsi_status = pReply->SCSIStatus; | ||
| 2695 | |||
| 2696 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 2697 | "IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh," | ||
| 2698 | "IOCLogInfo=%08xh\n", ioc->name, status, pReply->SCSIState, | ||
| 2699 | scsi_status, le32_to_cpu(pReply->IOCLogInfo))); | ||
| 2700 | |||
| 2701 | switch (status) { | ||
| 2702 | |||
| 2703 | case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ | ||
| 2704 | completion_code = MPT_SCANDV_SELECTION_TIMEOUT; | ||
| 2705 | break; | ||
| 2706 | |||
| 2707 | case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ | ||
| 2708 | case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ | ||
| 2709 | case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ | ||
| 2710 | case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ | ||
| 2711 | completion_code = MPT_SCANDV_DID_RESET; | ||
| 2712 | break; | ||
| 2713 | |||
| 2714 | case MPI_IOCSTATUS_BUSY: | ||
| 2715 | case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: | ||
| 2716 | completion_code = MPT_SCANDV_BUSY; | ||
| 2717 | break; | ||
| 2718 | |||
| 2719 | case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ | ||
| 2720 | case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ | ||
| 2721 | case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ | ||
| 2722 | if (pReply->Function == MPI_FUNCTION_CONFIG) { | ||
| 2723 | completion_code = MPT_SCANDV_GOOD; | ||
| 2724 | } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) { | ||
| 2725 | pr = (MpiRaidActionReply_t *)reply; | ||
| 2726 | if (le16_to_cpu(pr->ActionStatus) == | ||
| 2727 | MPI_RAID_ACTION_ASTATUS_SUCCESS) | ||
| 2728 | completion_code = MPT_SCANDV_GOOD; | ||
| 2729 | else | ||
| 2730 | completion_code = MPT_SCANDV_SOME_ERROR; | ||
| 2731 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) | ||
| 2732 | completion_code = MPT_SCANDV_SENSE; | ||
| 2733 | else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { | ||
| 2734 | if (req->u.scsireq.CDB[0] == INQUIRY) | ||
| 2735 | completion_code = MPT_SCANDV_ISSUE_SENSE; | ||
| 2736 | else | ||
| 2737 | completion_code = MPT_SCANDV_DID_RESET; | ||
| 2738 | } else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) | ||
| 2739 | completion_code = MPT_SCANDV_DID_RESET; | ||
| 2740 | else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
| 2741 | completion_code = MPT_SCANDV_DID_RESET; | ||
| 2742 | else if (scsi_status == MPI_SCSI_STATUS_BUSY) | ||
| 2743 | completion_code = MPT_SCANDV_BUSY; | ||
| 2744 | else | ||
| 2745 | completion_code = MPT_SCANDV_GOOD; | ||
| 2746 | break; | ||
| 2747 | |||
| 2748 | case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ | ||
| 2749 | if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
| 2750 | completion_code = MPT_SCANDV_DID_RESET; | ||
| 2751 | else | ||
| 2752 | completion_code = MPT_SCANDV_SOME_ERROR; | ||
| 2753 | break; | ||
| 2754 | default: | ||
| 2755 | completion_code = MPT_SCANDV_SOME_ERROR; | ||
| 2756 | break; | ||
| 2757 | |||
| 2758 | } /* switch(status) */ | ||
| 2759 | |||
| 2760 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
| 2761 | " completionCode set to %08xh\n", ioc->name, completion_code)); | ||
| 2762 | return completion_code; | ||
| 2763 | } | ||
| 3007 | 2764 | ||
| 3008 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2765 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 3009 | /** | 2766 | /** |
| @@ -3030,22 +2787,27 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
| 3030 | { | 2787 | { |
| 3031 | MPT_FRAME_HDR *mf; | 2788 | MPT_FRAME_HDR *mf; |
| 3032 | SCSIIORequest_t *pScsiReq; | 2789 | SCSIIORequest_t *pScsiReq; |
| 3033 | SCSIIORequest_t ReqCopy; | ||
| 3034 | int my_idx, ii, dir; | 2790 | int my_idx, ii, dir; |
| 3035 | int rc, cmdTimeout; | 2791 | int timeout; |
| 3036 | int in_isr; | ||
| 3037 | char cmdLen; | 2792 | char cmdLen; |
| 3038 | char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | 2793 | char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
| 3039 | char cmd = io->cmd; | 2794 | u8 cmd = io->cmd; |
| 3040 | MPT_ADAPTER *ioc = hd->ioc; | 2795 | MPT_ADAPTER *ioc = hd->ioc; |
| 2796 | int ret = 0; | ||
| 2797 | unsigned long timeleft; | ||
| 2798 | unsigned long flags; | ||
| 3041 | 2799 | ||
| 3042 | in_isr = in_interrupt(); | 2800 | /* don't send internal command during diag reset */ |
| 3043 | if (in_isr) { | 2801 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
| 3044 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n", | 2802 | if (ioc->ioc_reset_in_progress) { |
| 3045 | ioc->name)); | 2803 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); |
| 3046 | return -EPERM; | 2804 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 2805 | "%s: busy with host reset\n", ioc->name, __func__)); | ||
| 2806 | return MPT_SCANDV_BUSY; | ||
| 3047 | } | 2807 | } |
| 2808 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 3048 | 2809 | ||
| 2810 | mutex_lock(&ioc->internal_cmds.mutex); | ||
| 3049 | 2811 | ||
| 3050 | /* Set command specific information | 2812 | /* Set command specific information |
| 3051 | */ | 2813 | */ |
| @@ -3055,13 +2817,13 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
| 3055 | dir = MPI_SCSIIO_CONTROL_READ; | 2817 | dir = MPI_SCSIIO_CONTROL_READ; |
| 3056 | CDB[0] = cmd; | 2818 | CDB[0] = cmd; |
| 3057 | CDB[4] = io->size; | 2819 | CDB[4] = io->size; |
| 3058 | cmdTimeout = 10; | 2820 | timeout = 10; |
| 3059 | break; | 2821 | break; |
| 3060 | 2822 | ||
| 3061 | case TEST_UNIT_READY: | 2823 | case TEST_UNIT_READY: |
| 3062 | cmdLen = 6; | 2824 | cmdLen = 6; |
| 3063 | dir = MPI_SCSIIO_CONTROL_READ; | 2825 | dir = MPI_SCSIIO_CONTROL_READ; |
| 3064 | cmdTimeout = 10; | 2826 | timeout = 10; |
| 3065 | break; | 2827 | break; |
| 3066 | 2828 | ||
| 3067 | case START_STOP: | 2829 | case START_STOP: |
| @@ -3069,7 +2831,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
| 3069 | dir = MPI_SCSIIO_CONTROL_READ; | 2831 | dir = MPI_SCSIIO_CONTROL_READ; |
| 3070 | CDB[0] = cmd; | 2832 | CDB[0] = cmd; |
| 3071 | CDB[4] = 1; /*Spin up the disk */ | 2833 | CDB[4] = 1; /*Spin up the disk */ |
| 3072 | cmdTimeout = 15; | 2834 | timeout = 15; |
| 3073 | break; | 2835 | break; |
| 3074 | 2836 | ||
| 3075 | case REQUEST_SENSE: | 2837 | case REQUEST_SENSE: |
| @@ -3077,7 +2839,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
| 3077 | CDB[0] = cmd; | 2839 | CDB[0] = cmd; |
| 3078 | CDB[4] = io->size; | 2840 | CDB[4] = io->size; |
| 3079 | dir = MPI_SCSIIO_CONTROL_READ; | 2841 | dir = MPI_SCSIIO_CONTROL_READ; |
| 3080 | cmdTimeout = 10; | 2842 | timeout = 10; |
| 3081 | break; | 2843 | break; |
| 3082 | 2844 | ||
| 3083 | case READ_BUFFER: | 2845 | case READ_BUFFER: |
| @@ -3096,7 +2858,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
| 3096 | CDB[6] = (io->size >> 16) & 0xFF; | 2858 | CDB[6] = (io->size >> 16) & 0xFF; |
| 3097 | CDB[7] = (io->size >> 8) & 0xFF; | 2859 | CDB[7] = (io->size >> 8) & 0xFF; |
| 3098 | CDB[8] = io->size & 0xFF; | 2860 | CDB[8] = io->size & 0xFF; |
| 3099 | cmdTimeout = 10; | 2861 | timeout = 10; |
| 3100 | break; | 2862 | break; |
| 3101 | 2863 | ||
| 3102 | case WRITE_BUFFER: | 2864 | case WRITE_BUFFER: |
| @@ -3111,21 +2873,21 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
| 3111 | CDB[6] = (io->size >> 16) & 0xFF; | 2873 | CDB[6] = (io->size >> 16) & 0xFF; |
| 3112 | CDB[7] = (io->size >> 8) & 0xFF; | 2874 | CDB[7] = (io->size >> 8) & 0xFF; |
| 3113 | CDB[8] = io->size & 0xFF; | 2875 | CDB[8] = io->size & 0xFF; |
| 3114 | cmdTimeout = 10; | 2876 | timeout = 10; |
| 3115 | break; | 2877 | break; |
| 3116 | 2878 | ||
| 3117 | case RESERVE: | 2879 | case RESERVE: |
| 3118 | cmdLen = 6; | 2880 | cmdLen = 6; |
| 3119 | dir = MPI_SCSIIO_CONTROL_READ; | 2881 | dir = MPI_SCSIIO_CONTROL_READ; |
| 3120 | CDB[0] = cmd; | 2882 | CDB[0] = cmd; |
| 3121 | cmdTimeout = 10; | 2883 | timeout = 10; |
| 3122 | break; | 2884 | break; |
| 3123 | 2885 | ||
| 3124 | case RELEASE: | 2886 | case RELEASE: |
| 3125 | cmdLen = 6; | 2887 | cmdLen = 6; |
| 3126 | dir = MPI_SCSIIO_CONTROL_READ; | 2888 | dir = MPI_SCSIIO_CONTROL_READ; |
| 3127 | CDB[0] = cmd; | 2889 | CDB[0] = cmd; |
| 3128 | cmdTimeout = 10; | 2890 | timeout = 10; |
| 3129 | break; | 2891 | break; |
| 3130 | 2892 | ||
| 3131 | case SYNCHRONIZE_CACHE: | 2893 | case SYNCHRONIZE_CACHE: |
| @@ -3133,20 +2895,23 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
| 3133 | dir = MPI_SCSIIO_CONTROL_READ; | 2895 | dir = MPI_SCSIIO_CONTROL_READ; |
| 3134 | CDB[0] = cmd; | 2896 | CDB[0] = cmd; |
| 3135 | // CDB[1] = 0x02; /* set immediate bit */ | 2897 | // CDB[1] = 0x02; /* set immediate bit */ |
| 3136 | cmdTimeout = 10; | 2898 | timeout = 10; |
| 3137 | break; | 2899 | break; |
| 3138 | 2900 | ||
| 3139 | default: | 2901 | default: |
| 3140 | /* Error Case */ | 2902 | /* Error Case */ |
| 3141 | return -EFAULT; | 2903 | ret = -EFAULT; |
| 2904 | goto out; | ||
| 3142 | } | 2905 | } |
| 3143 | 2906 | ||
| 3144 | /* Get and Populate a free Frame | 2907 | /* Get and Populate a free Frame |
| 2908 | * MsgContext set in mpt_get_msg_frame call | ||
| 3145 | */ | 2909 | */ |
| 3146 | if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { | 2910 | if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { |
| 3147 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "No msg frames!\n", | 2911 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: No msg frames!\n", |
| 3148 | ioc->name)); | 2912 | ioc->name, __func__)); |
| 3149 | return -EBUSY; | 2913 | ret = MPT_SCANDV_BUSY; |
| 2914 | goto out; | ||
| 3150 | } | 2915 | } |
| 3151 | 2916 | ||
| 3152 | pScsiReq = (SCSIIORequest_t *) mf; | 2917 | pScsiReq = (SCSIIORequest_t *) mf; |
| @@ -3172,7 +2937,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
| 3172 | 2937 | ||
| 3173 | pScsiReq->Reserved = 0; | 2938 | pScsiReq->Reserved = 0; |
| 3174 | 2939 | ||
| 3175 | pScsiReq->MsgFlags = mpt_msg_flags(); | 2940 | pScsiReq->MsgFlags = mpt_msg_flags(ioc); |
| 3176 | /* MsgContext set in mpt_get_msg_fram call */ | 2941 | /* MsgContext set in mpt_get_msg_fram call */ |
| 3177 | 2942 | ||
| 3178 | int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN); | 2943 | int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN); |
| @@ -3184,74 +2949,58 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
| 3184 | 2949 | ||
| 3185 | if (cmd == REQUEST_SENSE) { | 2950 | if (cmd == REQUEST_SENSE) { |
| 3186 | pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); | 2951 | pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); |
| 3187 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n", | 2952 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 3188 | ioc->name, cmd)); | 2953 | "%s: Untagged! 0x%02x\n", ioc->name, __func__, cmd)); |
| 3189 | } | 2954 | } |
| 3190 | 2955 | ||
| 3191 | for (ii=0; ii < 16; ii++) | 2956 | for (ii = 0; ii < 16; ii++) |
| 3192 | pScsiReq->CDB[ii] = CDB[ii]; | 2957 | pScsiReq->CDB[ii] = CDB[ii]; |
| 3193 | 2958 | ||
| 3194 | pScsiReq->DataLength = cpu_to_le32(io->size); | 2959 | pScsiReq->DataLength = cpu_to_le32(io->size); |
| 3195 | pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma | 2960 | pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma |
| 3196 | + (my_idx * MPT_SENSE_BUFFER_ALLOC)); | 2961 | + (my_idx * MPT_SENSE_BUFFER_ALLOC)); |
| 3197 | 2962 | ||
| 3198 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n", | 2963 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 3199 | ioc->name, cmd, io->channel, io->id, io->lun)); | 2964 | "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n", |
| 2965 | ioc->name, __func__, cmd, io->channel, io->id, io->lun)); | ||
| 3200 | 2966 | ||
| 3201 | if (dir == MPI_SCSIIO_CONTROL_READ) { | 2967 | if (dir == MPI_SCSIIO_CONTROL_READ) |
| 3202 | mpt_add_sge((char *) &pScsiReq->SGL, | 2968 | ioc->add_sge((char *) &pScsiReq->SGL, |
| 3203 | MPT_SGE_FLAGS_SSIMPLE_READ | io->size, | 2969 | MPT_SGE_FLAGS_SSIMPLE_READ | io->size, io->data_dma); |
| 3204 | io->data_dma); | 2970 | else |
| 3205 | } else { | 2971 | ioc->add_sge((char *) &pScsiReq->SGL, |
| 3206 | mpt_add_sge((char *) &pScsiReq->SGL, | 2972 | MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, io->data_dma); |
| 3207 | MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, | ||
| 3208 | io->data_dma); | ||
| 3209 | } | ||
| 3210 | |||
| 3211 | /* The ISR will free the request frame, but we need | ||
| 3212 | * the information to initialize the target. Duplicate. | ||
| 3213 | */ | ||
| 3214 | memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t)); | ||
| 3215 | |||
| 3216 | /* Issue this command after: | ||
| 3217 | * finish init | ||
| 3218 | * add timer | ||
| 3219 | * Wait until the reply has been received | ||
| 3220 | * ScsiScanDvCtx callback function will | ||
| 3221 | * set hd->pLocal; | ||
| 3222 | * set scandv_wait_done and call wake_up | ||
| 3223 | */ | ||
| 3224 | hd->pLocal = NULL; | ||
| 3225 | hd->timer.expires = jiffies + HZ*cmdTimeout; | ||
| 3226 | hd->scandv_wait_done = 0; | ||
| 3227 | |||
| 3228 | /* Save cmd pointer, for resource free if timeout or | ||
| 3229 | * FW reload occurs | ||
| 3230 | */ | ||
| 3231 | hd->cmdPtr = mf; | ||
| 3232 | 2973 | ||
| 3233 | add_timer(&hd->timer); | 2974 | INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status) |
| 3234 | mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); | 2975 | mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); |
| 3235 | wait_event(hd->scandv_waitq, hd->scandv_wait_done); | 2976 | timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done, |
| 3236 | 2977 | timeout*HZ); | |
| 3237 | if (hd->pLocal) { | 2978 | if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { |
| 3238 | rc = hd->pLocal->completion; | 2979 | ret = MPT_SCANDV_DID_RESET; |
| 3239 | hd->pLocal->skip = 0; | 2980 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 3240 | 2981 | "%s: TIMED OUT for cmd=0x%02x\n", ioc->name, __func__, | |
| 3241 | /* Always set fatal error codes in some cases. | 2982 | cmd)); |
| 3242 | */ | 2983 | if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) { |
| 3243 | if (rc == MPT_SCANDV_SELECTION_TIMEOUT) | 2984 | mpt_free_msg_frame(ioc, mf); |
| 3244 | rc = -ENXIO; | 2985 | goto out; |
| 3245 | else if (rc == MPT_SCANDV_SOME_ERROR) | 2986 | } |
| 3246 | rc = -rc; | 2987 | if (!timeleft) { |
| 3247 | } else { | 2988 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", |
| 3248 | rc = -EFAULT; | 2989 | ioc->name, __func__); |
| 3249 | /* This should never happen. */ | 2990 | mpt_HardResetHandler(ioc, CAN_SLEEP); |
| 3250 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n", | 2991 | mpt_free_msg_frame(ioc, mf); |
| 3251 | ioc->name)); | 2992 | } |
| 2993 | goto out; | ||
| 3252 | } | 2994 | } |
| 3253 | 2995 | ||
| 3254 | return rc; | 2996 | ret = ioc->internal_cmds.completion_code; |
| 2997 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: success, rc=0x%02x\n", | ||
| 2998 | ioc->name, __func__, ret)); | ||
| 2999 | |||
| 3000 | out: | ||
| 3001 | CLEAR_MGMT_STATUS(ioc->internal_cmds.status) | ||
| 3002 | mutex_unlock(&ioc->internal_cmds.mutex); | ||
| 3003 | return ret; | ||
| 3255 | } | 3004 | } |
| 3256 | 3005 | ||
| 3257 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3006 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| @@ -3491,6 +3240,7 @@ struct device_attribute *mptscsih_host_attrs[] = { | |||
| 3491 | &dev_attr_debug_level, | 3240 | &dev_attr_debug_level, |
| 3492 | NULL, | 3241 | NULL, |
| 3493 | }; | 3242 | }; |
| 3243 | |||
| 3494 | EXPORT_SYMBOL(mptscsih_host_attrs); | 3244 | EXPORT_SYMBOL(mptscsih_host_attrs); |
| 3495 | 3245 | ||
| 3496 | EXPORT_SYMBOL(mptscsih_remove); | 3246 | EXPORT_SYMBOL(mptscsih_remove); |
| @@ -3516,6 +3266,5 @@ EXPORT_SYMBOL(mptscsih_event_process); | |||
| 3516 | EXPORT_SYMBOL(mptscsih_ioc_reset); | 3266 | EXPORT_SYMBOL(mptscsih_ioc_reset); |
| 3517 | EXPORT_SYMBOL(mptscsih_change_queue_depth); | 3267 | EXPORT_SYMBOL(mptscsih_change_queue_depth); |
| 3518 | EXPORT_SYMBOL(mptscsih_timer_expired); | 3268 | EXPORT_SYMBOL(mptscsih_timer_expired); |
| 3519 | EXPORT_SYMBOL(mptscsih_TMHandler); | ||
| 3520 | 3269 | ||
| 3521 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3270 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 319aa3033371..eb3f677528ac 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h | |||
| @@ -60,6 +60,7 @@ | |||
| 60 | #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) | 60 | #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) |
| 61 | #define MPT_SCANDV_ISSUE_SENSE (0x00000010) | 61 | #define MPT_SCANDV_ISSUE_SENSE (0x00000010) |
| 62 | #define MPT_SCANDV_FALLBACK (0x00000020) | 62 | #define MPT_SCANDV_FALLBACK (0x00000020) |
| 63 | #define MPT_SCANDV_BUSY (0x00000040) | ||
| 63 | 64 | ||
| 64 | #define MPT_SCANDV_MAX_RETRIES (10) | 65 | #define MPT_SCANDV_MAX_RETRIES (10) |
| 65 | 66 | ||
| @@ -89,6 +90,7 @@ | |||
| 89 | 90 | ||
| 90 | #endif | 91 | #endif |
| 91 | 92 | ||
| 93 | |||
| 92 | typedef struct _internal_cmd { | 94 | typedef struct _internal_cmd { |
| 93 | char *data; /* data pointer */ | 95 | char *data; /* data pointer */ |
| 94 | dma_addr_t data_dma; /* data dma address */ | 96 | dma_addr_t data_dma; /* data dma address */ |
| @@ -112,6 +114,8 @@ extern int mptscsih_resume(struct pci_dev *pdev); | |||
| 112 | extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func); | 114 | extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func); |
| 113 | extern const char * mptscsih_info(struct Scsi_Host *SChost); | 115 | extern const char * mptscsih_info(struct Scsi_Host *SChost); |
| 114 | extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)); | 116 | extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)); |
| 117 | extern int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, | ||
| 118 | u8 id, int lun, int ctx2abort, ulong timeout); | ||
| 115 | extern void mptscsih_slave_destroy(struct scsi_device *device); | 119 | extern void mptscsih_slave_destroy(struct scsi_device *device); |
| 116 | extern int mptscsih_slave_configure(struct scsi_device *device); | 120 | extern int mptscsih_slave_configure(struct scsi_device *device); |
| 117 | extern int mptscsih_abort(struct scsi_cmnd * SCpnt); | 121 | extern int mptscsih_abort(struct scsi_cmnd * SCpnt); |
| @@ -126,7 +130,8 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE | |||
| 126 | extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); | 130 | extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); |
| 127 | extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); | 131 | extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); |
| 128 | extern void mptscsih_timer_expired(unsigned long data); | 132 | extern void mptscsih_timer_expired(unsigned long data); |
| 129 | extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); | ||
| 130 | extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id); | 133 | extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id); |
| 131 | extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id); | 134 | extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id); |
| 132 | extern struct device_attribute *mptscsih_host_attrs[]; | 135 | extern struct device_attribute *mptscsih_host_attrs[]; |
| 136 | extern struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i); | ||
| 137 | extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code); | ||
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 61620144e49c..c5b808fd55ba 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c | |||
| @@ -300,7 +300,7 @@ mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id) | |||
| 300 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | | 300 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | |
| 301 | (IOCPage4Ptr->Header.PageLength + ii) * 4; | 301 | (IOCPage4Ptr->Header.PageLength + ii) * 4; |
| 302 | 302 | ||
| 303 | mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); | 303 | ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); |
| 304 | 304 | ||
| 305 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 305 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 306 | "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", | 306 | "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", |
| @@ -614,19 +614,24 @@ static void mptspi_read_parameters(struct scsi_target *starget) | |||
| 614 | spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0; | 614 | spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0; |
| 615 | } | 615 | } |
| 616 | 616 | ||
| 617 | static int | 617 | int |
| 618 | mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) | 618 | mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) |
| 619 | { | 619 | { |
| 620 | MPT_ADAPTER *ioc = hd->ioc; | ||
| 620 | MpiRaidActionRequest_t *pReq; | 621 | MpiRaidActionRequest_t *pReq; |
| 621 | MPT_FRAME_HDR *mf; | 622 | MPT_FRAME_HDR *mf; |
| 622 | MPT_ADAPTER *ioc = hd->ioc; | 623 | int ret; |
| 624 | unsigned long timeleft; | ||
| 625 | |||
| 626 | mutex_lock(&ioc->internal_cmds.mutex); | ||
| 623 | 627 | ||
| 624 | /* Get and Populate a free Frame | 628 | /* Get and Populate a free Frame |
| 625 | */ | 629 | */ |
| 626 | if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { | 630 | if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { |
| 627 | ddvprintk(ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", | 631 | dfailprintk(hd->ioc, printk(MYIOC_s_WARN_FMT |
| 628 | ioc->name)); | 632 | "%s: no msg frames!\n", ioc->name, __func__)); |
| 629 | return -EAGAIN; | 633 | ret = -EAGAIN; |
| 634 | goto out; | ||
| 630 | } | 635 | } |
| 631 | pReq = (MpiRaidActionRequest_t *)mf; | 636 | pReq = (MpiRaidActionRequest_t *)mf; |
| 632 | if (quiesce) | 637 | if (quiesce) |
| @@ -643,29 +648,36 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) | |||
| 643 | pReq->Reserved2 = 0; | 648 | pReq->Reserved2 = 0; |
| 644 | pReq->ActionDataWord = 0; /* Reserved for this action */ | 649 | pReq->ActionDataWord = 0; /* Reserved for this action */ |
| 645 | 650 | ||
| 646 | mpt_add_sge((char *)&pReq->ActionDataSGE, | 651 | ioc->add_sge((char *)&pReq->ActionDataSGE, |
| 647 | MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); | 652 | MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); |
| 648 | 653 | ||
| 649 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n", | 654 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n", |
| 650 | ioc->name, pReq->Action, channel, id)); | 655 | ioc->name, pReq->Action, channel, id)); |
| 651 | 656 | ||
| 652 | hd->pLocal = NULL; | 657 | INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status) |
| 653 | hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ | ||
| 654 | hd->scandv_wait_done = 0; | ||
| 655 | |||
| 656 | /* Save cmd pointer, for resource free if timeout or | ||
| 657 | * FW reload occurs | ||
| 658 | */ | ||
| 659 | hd->cmdPtr = mf; | ||
| 660 | |||
| 661 | add_timer(&hd->timer); | ||
| 662 | mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); | 658 | mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); |
| 663 | wait_event(hd->scandv_waitq, hd->scandv_wait_done); | 659 | timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done, 10*HZ); |
| 660 | if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | ||
| 661 | ret = -ETIME; | ||
| 662 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: TIMED OUT!\n", | ||
| 663 | ioc->name, __func__)); | ||
| 664 | if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) | ||
| 665 | goto out; | ||
| 666 | if (!timeleft) { | ||
| 667 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", | ||
| 668 | ioc->name, __func__); | ||
| 669 | mpt_HardResetHandler(ioc, CAN_SLEEP); | ||
| 670 | mpt_free_msg_frame(ioc, mf); | ||
| 671 | } | ||
| 672 | goto out; | ||
| 673 | } | ||
| 664 | 674 | ||
| 665 | if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0)) | 675 | ret = ioc->internal_cmds.completion_code; |
| 666 | return -1; | ||
| 667 | 676 | ||
| 668 | return 0; | 677 | out: |
| 678 | CLEAR_MGMT_STATUS(ioc->internal_cmds.status) | ||
| 679 | mutex_unlock(&ioc->internal_cmds.mutex); | ||
| 680 | return ret; | ||
| 669 | } | 681 | } |
| 670 | 682 | ||
| 671 | static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, | 683 | static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, |
| @@ -1423,17 +1435,15 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1423 | * A slightly different algorithm is required for | 1435 | * A slightly different algorithm is required for |
| 1424 | * 64bit SGEs. | 1436 | * 64bit SGEs. |
| 1425 | */ | 1437 | */ |
| 1426 | scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); | 1438 | scale = ioc->req_sz/ioc->SGE_size; |
| 1427 | if (sizeof(dma_addr_t) == sizeof(u64)) { | 1439 | if (ioc->sg_addr_size == sizeof(u64)) { |
| 1428 | numSGE = (scale - 1) * | 1440 | numSGE = (scale - 1) * |
| 1429 | (ioc->facts.MaxChainDepth-1) + scale + | 1441 | (ioc->facts.MaxChainDepth-1) + scale + |
| 1430 | (ioc->req_sz - 60) / (sizeof(dma_addr_t) + | 1442 | (ioc->req_sz - 60) / ioc->SGE_size; |
| 1431 | sizeof(u32)); | ||
| 1432 | } else { | 1443 | } else { |
| 1433 | numSGE = 1 + (scale - 1) * | 1444 | numSGE = 1 + (scale - 1) * |
| 1434 | (ioc->facts.MaxChainDepth-1) + scale + | 1445 | (ioc->facts.MaxChainDepth-1) + scale + |
| 1435 | (ioc->req_sz - 64) / (sizeof(dma_addr_t) + | 1446 | (ioc->req_sz - 64) / ioc->SGE_size; |
| 1436 | sizeof(u32)); | ||
| 1437 | } | 1447 | } |
| 1438 | 1448 | ||
| 1439 | if (numSGE < sh->sg_tablesize) { | 1449 | if (numSGE < sh->sg_tablesize) { |
| @@ -1464,9 +1474,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1464 | 1474 | ||
| 1465 | /* Clear the TM flags | 1475 | /* Clear the TM flags |
| 1466 | */ | 1476 | */ |
| 1467 | hd->tmPending = 0; | ||
| 1468 | hd->tmState = TM_STATE_NONE; | ||
| 1469 | hd->resetPending = 0; | ||
| 1470 | hd->abortSCpnt = NULL; | 1477 | hd->abortSCpnt = NULL; |
| 1471 | 1478 | ||
| 1472 | /* Clear the pointer used to store | 1479 | /* Clear the pointer used to store |
| @@ -1493,8 +1500,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1493 | mpt_saf_te)); | 1500 | mpt_saf_te)); |
| 1494 | ioc->spi_data.noQas = 0; | 1501 | ioc->spi_data.noQas = 0; |
| 1495 | 1502 | ||
| 1496 | init_waitqueue_head(&hd->scandv_waitq); | ||
| 1497 | hd->scandv_wait_done = 0; | ||
| 1498 | hd->last_queue_full = 0; | 1503 | hd->last_queue_full = 0; |
| 1499 | hd->spi_pending = 0; | 1504 | hd->spi_pending = 0; |
| 1500 | 1505 | ||
| @@ -1514,7 +1519,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1514 | * issue internal bus reset | 1519 | * issue internal bus reset |
| 1515 | */ | 1520 | */ |
| 1516 | if (ioc->spi_data.bus_reset) | 1521 | if (ioc->spi_data.bus_reset) |
| 1517 | mptscsih_TMHandler(hd, | 1522 | mptscsih_IssueTaskMgmt(hd, |
| 1518 | MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | 1523 | MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, |
| 1519 | 0, 0, 0, 0, 5); | 1524 | 0, 0, 0, 0, 5); |
| 1520 | 1525 | ||
