diff options
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r-- | drivers/message/fusion/lsi/mpi_history.txt | 6 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.c | 1570 | ||||
-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 | 3136 | ||||
-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 |
11 files changed, 4582 insertions, 2468 deletions
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt index 693e4b511354..fa9249b4971a 100644 --- a/drivers/message/fusion/lsi/mpi_history.txt +++ b/drivers/message/fusion/lsi/mpi_history.txt | |||
@@ -130,7 +130,7 @@ mpi_ioc.h | |||
130 | * 08-08-01 01.02.01 Original release for v1.2 work. | 130 | * 08-08-01 01.02.01 Original release for v1.2 work. |
131 | * New format for FWVersion and ProductId in | 131 | * New format for FWVersion and ProductId in |
132 | * MSG_IOC_FACTS_REPLY and MPI_FW_HEADER. | 132 | * MSG_IOC_FACTS_REPLY and MPI_FW_HEADER. |
133 | * 08-31-01 01.02.02 Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and | 133 | * 08-31-01 01.02.02 Added event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and |
134 | * related structure and defines. | 134 | * related structure and defines. |
135 | * Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED. | 135 | * Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED. |
136 | * Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE. | 136 | * Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE. |
@@ -190,7 +190,7 @@ mpi_ioc.h | |||
190 | * 10-11-06 01.05.12 Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED. | 190 | * 10-11-06 01.05.12 Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED. |
191 | * Added MaxInitiators field to PortFacts reply. | 191 | * Added MaxInitiators field to PortFacts reply. |
192 | * Added SAS Device Status Change ReasonCode for | 192 | * Added SAS Device Status Change ReasonCode for |
193 | * asynchronous notificaiton. | 193 | * asynchronous notification. |
194 | * Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event | 194 | * Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event |
195 | * data structure. | 195 | * data structure. |
196 | * Added new ImageType values for FWDownload and FWUpload | 196 | * Added new ImageType values for FWDownload and FWUpload |
@@ -623,7 +623,7 @@ mpi_fc.h | |||
623 | * 11-02-00 01.01.01 Original release for post 1.0 work | 623 | * 11-02-00 01.01.01 Original release for post 1.0 work |
624 | * 12-04-00 01.01.02 Added messages for Common Transport Send and | 624 | * 12-04-00 01.01.02 Added messages for Common Transport Send and |
625 | * Primitive Send. | 625 | * Primitive Send. |
626 | * 01-09-01 01.01.03 Modifed some of the new flags to have an MPI prefix | 626 | * 01-09-01 01.01.03 Modified some of the new flags to have an MPI prefix |
627 | * and modified the FcPrimitiveSend flags. | 627 | * and modified the FcPrimitiveSend flags. |
628 | * 01-25-01 01.01.04 Move InitiatorIndex in LinkServiceRsp reply to a larger | 628 | * 01-25-01 01.01.04 Move InitiatorIndex in LinkServiceRsp reply to a larger |
629 | * field. | 629 | * field. |
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 5d496a99e034..0df065275cd3 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,116 @@ 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 (1078 workaround). | ||
1027 | * @pAddr: virtual address for SGE | ||
1028 | * @flagslength: SGE flags and data transfer length | ||
1029 | * @dma_addr: Physical address | ||
1030 | * | ||
1031 | * This routine places a MPT request frame back on the MPT adapter's | ||
1032 | * FreeQ. | ||
1033 | **/ | ||
1034 | static void | ||
1035 | mpt_add_sge_64bit_1078(void *pAddr, u32 flagslength, dma_addr_t dma_addr) | ||
1036 | { | ||
1037 | SGESimple64_t *pSge = (SGESimple64_t *) pAddr; | ||
1038 | u32 tmp; | ||
1039 | |||
1040 | pSge->Address.Low = cpu_to_le32 | ||
1041 | (lower_32_bits((unsigned long)(dma_addr))); | ||
1042 | tmp = (u32)(upper_32_bits((unsigned long)dma_addr)); | ||
1043 | |||
1044 | /* | ||
1045 | * 1078 errata workaround for the 36GB limitation | ||
1046 | */ | ||
1047 | if ((((u64)dma_addr + MPI_SGE_LENGTH(flagslength)) >> 32) == 9) { | ||
1048 | flagslength |= | ||
1049 | MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_LOCAL_ADDRESS); | ||
1050 | tmp |= (1<<31); | ||
1051 | if (mpt_debug_level & MPT_DEBUG_36GB_MEM) | ||
1052 | printk(KERN_DEBUG "1078 P0M2 addressing for " | ||
1053 | "addr = 0x%llx len = %d\n", | ||
1054 | (unsigned long long)dma_addr, | ||
1055 | MPI_SGE_LENGTH(flagslength)); | ||
1056 | } | ||
1057 | |||
1058 | pSge->Address.High = cpu_to_le32(tmp); | ||
1059 | pSge->FlagsLength = cpu_to_le32( | ||
1060 | (flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING)); | ||
1061 | } | ||
1062 | |||
1063 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
1064 | /** | ||
1065 | * mpt_add_chain - Place a 32 bit chain SGE at address pAddr. | ||
1066 | * @pAddr: virtual address for SGE | ||
1067 | * @next: nextChainOffset value (u32's) | ||
1068 | * @length: length of next SGL segment | ||
1069 | * @dma_addr: Physical address | ||
1070 | * | ||
1071 | */ | ||
1072 | static void | ||
1073 | mpt_add_chain(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr) | ||
1074 | { | ||
1075 | SGEChain32_t *pChain = (SGEChain32_t *) pAddr; | ||
1076 | pChain->Length = cpu_to_le16(length); | ||
1077 | pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT; | ||
1078 | pChain->NextChainOffset = next; | ||
1079 | pChain->Address = cpu_to_le32(dma_addr); | ||
1080 | } | ||
1081 | |||
1082 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
1083 | /** | ||
1084 | * mpt_add_chain_64bit - Place a 64 bit chain SGE at address pAddr. | ||
1085 | * @pAddr: virtual address for SGE | ||
1086 | * @next: nextChainOffset value (u32's) | ||
1087 | * @length: length of next SGL segment | ||
1088 | * @dma_addr: Physical address | ||
1089 | * | ||
1090 | */ | ||
1091 | static void | ||
1092 | mpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr) | ||
1093 | { | ||
1094 | SGEChain64_t *pChain = (SGEChain64_t *) pAddr; | ||
1014 | u32 tmp = dma_addr & 0xFFFFFFFF; | 1095 | u32 tmp = dma_addr & 0xFFFFFFFF; |
1015 | 1096 | ||
1016 | pSge->FlagsLength = cpu_to_le32(flagslength); | 1097 | pChain->Length = cpu_to_le16(length); |
1017 | pSge->Address.Low = cpu_to_le32(tmp); | 1098 | pChain->Flags = (MPI_SGE_FLAGS_CHAIN_ELEMENT | |
1018 | tmp = (u32) ((u64)dma_addr >> 32); | 1099 | MPI_SGE_FLAGS_64_BIT_ADDRESSING); |
1019 | pSge->Address.High = cpu_to_le32(tmp); | ||
1020 | 1100 | ||
1021 | } else { | 1101 | pChain->NextChainOffset = next; |
1022 | SGESimple32_t *pSge = (SGESimple32_t *) pAddr; | 1102 | |
1023 | pSge->FlagsLength = cpu_to_le32(flagslength); | 1103 | pChain->Address.Low = cpu_to_le32(tmp); |
1024 | pSge->Address = cpu_to_le32(dma_addr); | 1104 | tmp = (u32)(upper_32_bits((unsigned long)dma_addr)); |
1025 | } | 1105 | pChain->Address.High = cpu_to_le32(tmp); |
1026 | } | 1106 | } |
1027 | 1107 | ||
1028 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1108 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -1225,7 +1305,7 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init) | |||
1225 | } | 1305 | } |
1226 | flags_length = flags_length << MPI_SGE_FLAGS_SHIFT; | 1306 | flags_length = flags_length << MPI_SGE_FLAGS_SHIFT; |
1227 | flags_length |= ioc->HostPageBuffer_sz; | 1307 | flags_length |= ioc->HostPageBuffer_sz; |
1228 | mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma); | 1308 | ioc->add_sge(psge, flags_length, ioc->HostPageBuffer_dma); |
1229 | ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE; | 1309 | ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE; |
1230 | 1310 | ||
1231 | return 0; | 1311 | return 0; |
@@ -1534,21 +1614,42 @@ mpt_mapresources(MPT_ADAPTER *ioc) | |||
1534 | 1614 | ||
1535 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); | 1615 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); |
1536 | 1616 | ||
1537 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) | 1617 | if (sizeof(dma_addr_t) > 4) { |
1538 | && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { | 1618 | const uint64_t required_mask = dma_get_required_mask |
1539 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | 1619 | (&pdev->dev); |
1540 | ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", | 1620 | if (required_mask > DMA_BIT_MASK(32) |
1541 | ioc->name)); | 1621 | && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) |
1542 | } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) | 1622 | && !pci_set_consistent_dma_mask(pdev, |
1543 | && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { | 1623 | DMA_BIT_MASK(64))) { |
1544 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | 1624 | ioc->dma_mask = DMA_BIT_MASK(64); |
1545 | ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", | 1625 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT |
1546 | ioc->name)); | 1626 | ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", |
1627 | ioc->name)); | ||
1628 | } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) | ||
1629 | && !pci_set_consistent_dma_mask(pdev, | ||
1630 | DMA_BIT_MASK(32))) { | ||
1631 | ioc->dma_mask = DMA_BIT_MASK(32); | ||
1632 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | ||
1633 | ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", | ||
1634 | ioc->name)); | ||
1635 | } else { | ||
1636 | printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n", | ||
1637 | ioc->name, pci_name(pdev)); | ||
1638 | return r; | ||
1639 | } | ||
1547 | } else { | 1640 | } else { |
1548 | printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n", | 1641 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) |
1549 | ioc->name, pci_name(pdev)); | 1642 | && !pci_set_consistent_dma_mask(pdev, |
1550 | pci_release_selected_regions(pdev, ioc->bars); | 1643 | DMA_BIT_MASK(32))) { |
1551 | return r; | 1644 | ioc->dma_mask = DMA_BIT_MASK(32); |
1645 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | ||
1646 | ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", | ||
1647 | ioc->name)); | ||
1648 | } else { | ||
1649 | printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n", | ||
1650 | ioc->name, pci_name(pdev)); | ||
1651 | return r; | ||
1652 | } | ||
1552 | } | 1653 | } |
1553 | 1654 | ||
1554 | mem_phys = msize = 0; | 1655 | mem_phys = msize = 0; |
@@ -1632,6 +1733,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1632 | 1733 | ||
1633 | ioc->id = mpt_ids++; | 1734 | ioc->id = mpt_ids++; |
1634 | sprintf(ioc->name, "ioc%d", ioc->id); | 1735 | sprintf(ioc->name, "ioc%d", ioc->id); |
1736 | dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n")); | ||
1635 | 1737 | ||
1636 | /* | 1738 | /* |
1637 | * set initial debug level | 1739 | * set initial debug level |
@@ -1650,14 +1752,36 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1650 | return r; | 1752 | return r; |
1651 | } | 1753 | } |
1652 | 1754 | ||
1755 | /* | ||
1756 | * Setting up proper handlers for scatter gather handling | ||
1757 | */ | ||
1758 | if (ioc->dma_mask == DMA_BIT_MASK(64)) { | ||
1759 | if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) | ||
1760 | ioc->add_sge = &mpt_add_sge_64bit_1078; | ||
1761 | else | ||
1762 | ioc->add_sge = &mpt_add_sge_64bit; | ||
1763 | ioc->add_chain = &mpt_add_chain_64bit; | ||
1764 | ioc->sg_addr_size = 8; | ||
1765 | } else { | ||
1766 | ioc->add_sge = &mpt_add_sge; | ||
1767 | ioc->add_chain = &mpt_add_chain; | ||
1768 | ioc->sg_addr_size = 4; | ||
1769 | } | ||
1770 | ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size; | ||
1771 | |||
1653 | ioc->alloc_total = sizeof(MPT_ADAPTER); | 1772 | ioc->alloc_total = sizeof(MPT_ADAPTER); |
1654 | ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ | 1773 | ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ |
1655 | ioc->reply_sz = MPT_REPLY_FRAME_SIZE; | 1774 | ioc->reply_sz = MPT_REPLY_FRAME_SIZE; |
1656 | 1775 | ||
1657 | ioc->pcidev = pdev; | 1776 | ioc->pcidev = pdev; |
1658 | ioc->diagPending = 0; | 1777 | |
1659 | spin_lock_init(&ioc->diagLock); | 1778 | spin_lock_init(&ioc->taskmgmt_lock); |
1660 | spin_lock_init(&ioc->initializing_hba_lock); | 1779 | mutex_init(&ioc->internal_cmds.mutex); |
1780 | init_completion(&ioc->internal_cmds.done); | ||
1781 | mutex_init(&ioc->mptbase_cmds.mutex); | ||
1782 | init_completion(&ioc->mptbase_cmds.done); | ||
1783 | mutex_init(&ioc->taskmgmt_cmds.mutex); | ||
1784 | init_completion(&ioc->taskmgmt_cmds.done); | ||
1661 | 1785 | ||
1662 | /* Initialize the event logging. | 1786 | /* Initialize the event logging. |
1663 | */ | 1787 | */ |
@@ -1670,16 +1794,13 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1670 | ioc->mfcnt = 0; | 1794 | ioc->mfcnt = 0; |
1671 | #endif | 1795 | #endif |
1672 | 1796 | ||
1797 | ioc->sh = NULL; | ||
1673 | ioc->cached_fw = NULL; | 1798 | ioc->cached_fw = NULL; |
1674 | 1799 | ||
1675 | /* Initilize SCSI Config Data structure | 1800 | /* Initilize SCSI Config Data structure |
1676 | */ | 1801 | */ |
1677 | memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); | 1802 | memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); |
1678 | 1803 | ||
1679 | /* Initialize the running configQ head. | ||
1680 | */ | ||
1681 | INIT_LIST_HEAD(&ioc->configQ); | ||
1682 | |||
1683 | /* Initialize the fc rport list head. | 1804 | /* Initialize the fc rport list head. |
1684 | */ | 1805 | */ |
1685 | INIT_LIST_HEAD(&ioc->fc_rports); | 1806 | INIT_LIST_HEAD(&ioc->fc_rports); |
@@ -1690,9 +1811,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1690 | 1811 | ||
1691 | /* Initialize workqueue */ | 1812 | /* Initialize workqueue */ |
1692 | INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work); | 1813 | INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work); |
1693 | spin_lock_init(&ioc->fault_reset_work_lock); | ||
1694 | 1814 | ||
1695 | snprintf(ioc->reset_work_q_name, sizeof(ioc->reset_work_q_name), | 1815 | snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN, |
1696 | "mpt_poll_%d", ioc->id); | 1816 | "mpt_poll_%d", ioc->id); |
1697 | ioc->reset_work_q = | 1817 | ioc->reset_work_q = |
1698 | create_singlethread_workqueue(ioc->reset_work_q_name); | 1818 | create_singlethread_workqueue(ioc->reset_work_q_name); |
@@ -1767,11 +1887,14 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1767 | case MPI_MANUFACTPAGE_DEVID_SAS1064: | 1887 | case MPI_MANUFACTPAGE_DEVID_SAS1064: |
1768 | case MPI_MANUFACTPAGE_DEVID_SAS1068: | 1888 | case MPI_MANUFACTPAGE_DEVID_SAS1068: |
1769 | ioc->errata_flag_1064 = 1; | 1889 | ioc->errata_flag_1064 = 1; |
1890 | ioc->bus_type = SAS; | ||
1891 | break; | ||
1770 | 1892 | ||
1771 | case MPI_MANUFACTPAGE_DEVID_SAS1064E: | 1893 | case MPI_MANUFACTPAGE_DEVID_SAS1064E: |
1772 | case MPI_MANUFACTPAGE_DEVID_SAS1068E: | 1894 | case MPI_MANUFACTPAGE_DEVID_SAS1068E: |
1773 | case MPI_MANUFACTPAGE_DEVID_SAS1078: | 1895 | case MPI_MANUFACTPAGE_DEVID_SAS1078: |
1774 | ioc->bus_type = SAS; | 1896 | ioc->bus_type = SAS; |
1897 | break; | ||
1775 | } | 1898 | } |
1776 | 1899 | ||
1777 | 1900 | ||
@@ -1813,6 +1936,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1813 | */ | 1936 | */ |
1814 | mpt_detect_bound_ports(ioc, pdev); | 1937 | mpt_detect_bound_ports(ioc, pdev); |
1815 | 1938 | ||
1939 | INIT_LIST_HEAD(&ioc->fw_event_list); | ||
1940 | spin_lock_init(&ioc->fw_event_lock); | ||
1941 | snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id); | ||
1942 | ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name); | ||
1943 | |||
1816 | if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, | 1944 | if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, |
1817 | CAN_SLEEP)) != 0){ | 1945 | CAN_SLEEP)) != 0){ |
1818 | printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n", | 1946 | printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n", |
@@ -1885,13 +2013,18 @@ mpt_detach(struct pci_dev *pdev) | |||
1885 | /* | 2013 | /* |
1886 | * Stop polling ioc for fault condition | 2014 | * Stop polling ioc for fault condition |
1887 | */ | 2015 | */ |
1888 | spin_lock_irqsave(&ioc->fault_reset_work_lock, flags); | 2016 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
1889 | wq = ioc->reset_work_q; | 2017 | wq = ioc->reset_work_q; |
1890 | ioc->reset_work_q = NULL; | 2018 | ioc->reset_work_q = NULL; |
1891 | spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags); | 2019 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); |
1892 | cancel_delayed_work(&ioc->fault_reset_work); | 2020 | cancel_delayed_work(&ioc->fault_reset_work); |
1893 | destroy_workqueue(wq); | 2021 | destroy_workqueue(wq); |
1894 | 2022 | ||
2023 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
2024 | wq = ioc->fw_event_q; | ||
2025 | ioc->fw_event_q = NULL; | ||
2026 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
2027 | destroy_workqueue(wq); | ||
1895 | 2028 | ||
1896 | sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); | 2029 | sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); |
1897 | remove_proc_entry(pname, NULL); | 2030 | remove_proc_entry(pname, NULL); |
@@ -1994,6 +2127,21 @@ mpt_resume(struct pci_dev *pdev) | |||
1994 | if (err) | 2127 | if (err) |
1995 | return err; | 2128 | return err; |
1996 | 2129 | ||
2130 | if (ioc->dma_mask == DMA_BIT_MASK(64)) { | ||
2131 | if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) | ||
2132 | ioc->add_sge = &mpt_add_sge_64bit_1078; | ||
2133 | else | ||
2134 | ioc->add_sge = &mpt_add_sge_64bit; | ||
2135 | ioc->add_chain = &mpt_add_chain_64bit; | ||
2136 | ioc->sg_addr_size = 8; | ||
2137 | } else { | ||
2138 | |||
2139 | ioc->add_sge = &mpt_add_sge; | ||
2140 | ioc->add_chain = &mpt_add_chain; | ||
2141 | ioc->sg_addr_size = 4; | ||
2142 | } | ||
2143 | ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size; | ||
2144 | |||
1997 | printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", | 2145 | 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), | 2146 | ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT), |
1999 | CHIPREG_READ32(&ioc->chip->Doorbell)); | 2147 | CHIPREG_READ32(&ioc->chip->Doorbell)); |
@@ -2091,12 +2239,16 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2091 | ioc->active = 0; | 2239 | ioc->active = 0; |
2092 | 2240 | ||
2093 | if (ioc->alt_ioc) { | 2241 | if (ioc->alt_ioc) { |
2094 | if (ioc->alt_ioc->active) | 2242 | if (ioc->alt_ioc->active || |
2243 | reason == MPT_HOSTEVENT_IOC_RECOVER) { | ||
2095 | reset_alt_ioc_active = 1; | 2244 | reset_alt_ioc_active = 1; |
2096 | 2245 | /* Disable alt-IOC's reply interrupts | |
2097 | /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */ | 2246 | * (and FreeQ) for a bit |
2098 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF); | 2247 | **/ |
2099 | ioc->alt_ioc->active = 0; | 2248 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, |
2249 | 0xFFFFFFFF); | ||
2250 | ioc->alt_ioc->active = 0; | ||
2251 | } | ||
2100 | } | 2252 | } |
2101 | 2253 | ||
2102 | hard = 1; | 2254 | hard = 1; |
@@ -2117,9 +2269,11 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2117 | } | 2269 | } |
2118 | 2270 | ||
2119 | } else { | 2271 | } else { |
2120 | printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name); | 2272 | printk(MYIOC_s_WARN_FMT |
2273 | "NOT READY WARNING!\n", ioc->name); | ||
2121 | } | 2274 | } |
2122 | return -1; | 2275 | ret = -1; |
2276 | goto out; | ||
2123 | } | 2277 | } |
2124 | 2278 | ||
2125 | /* hard_reset_done = 0 if a soft reset was performed | 2279 | /* hard_reset_done = 0 if a soft reset was performed |
@@ -2129,7 +2283,9 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2129 | if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) | 2283 | if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) |
2130 | alt_ioc_ready = 1; | 2284 | alt_ioc_ready = 1; |
2131 | else | 2285 | else |
2132 | printk(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name); | 2286 | printk(MYIOC_s_WARN_FMT |
2287 | ": alt-ioc Not ready WARNING!\n", | ||
2288 | ioc->alt_ioc->name); | ||
2133 | } | 2289 | } |
2134 | 2290 | ||
2135 | for (ii=0; ii<5; ii++) { | 2291 | for (ii=0; ii<5; ii++) { |
@@ -2150,7 +2306,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2150 | if (alt_ioc_ready) { | 2306 | if (alt_ioc_ready) { |
2151 | if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { | 2307 | if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { |
2152 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 2308 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2153 | "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc)); | 2309 | "Initial Alt IocFacts failed rc=%x\n", |
2310 | ioc->name, rc)); | ||
2154 | /* Retry - alt IOC was initialized once | 2311 | /* Retry - alt IOC was initialized once |
2155 | */ | 2312 | */ |
2156 | rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); | 2313 | rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); |
@@ -2194,16 +2351,20 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2194 | IRQF_SHARED, ioc->name, ioc); | 2351 | IRQF_SHARED, ioc->name, ioc); |
2195 | if (rc < 0) { | 2352 | if (rc < 0) { |
2196 | printk(MYIOC_s_ERR_FMT "Unable to allocate " | 2353 | printk(MYIOC_s_ERR_FMT "Unable to allocate " |
2197 | "interrupt %d!\n", ioc->name, ioc->pcidev->irq); | 2354 | "interrupt %d!\n", |
2355 | ioc->name, ioc->pcidev->irq); | ||
2198 | if (ioc->msi_enable) | 2356 | if (ioc->msi_enable) |
2199 | pci_disable_msi(ioc->pcidev); | 2357 | pci_disable_msi(ioc->pcidev); |
2200 | return -EBUSY; | 2358 | ret = -EBUSY; |
2359 | goto out; | ||
2201 | } | 2360 | } |
2202 | irq_allocated = 1; | 2361 | irq_allocated = 1; |
2203 | ioc->pci_irq = ioc->pcidev->irq; | 2362 | ioc->pci_irq = ioc->pcidev->irq; |
2204 | pci_set_master(ioc->pcidev); /* ?? */ | 2363 | pci_set_master(ioc->pcidev); /* ?? */ |
2205 | dprintk(ioc, printk(MYIOC_s_INFO_FMT "installed at interrupt " | 2364 | pci_set_drvdata(ioc->pcidev, ioc); |
2206 | "%d\n", ioc->name, ioc->pcidev->irq)); | 2365 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT |
2366 | "installed at interrupt %d\n", ioc->name, | ||
2367 | ioc->pcidev->irq)); | ||
2207 | } | 2368 | } |
2208 | } | 2369 | } |
2209 | 2370 | ||
@@ -2212,17 +2373,22 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2212 | * init as upper addresses are needed for init. | 2373 | * init as upper addresses are needed for init. |
2213 | * If fails, continue with alt-ioc processing | 2374 | * If fails, continue with alt-ioc processing |
2214 | */ | 2375 | */ |
2376 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "PrimeIocFifos\n", | ||
2377 | ioc->name)); | ||
2215 | if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0)) | 2378 | if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0)) |
2216 | ret = -3; | 2379 | ret = -3; |
2217 | 2380 | ||
2218 | /* May need to check/upload firmware & data here! | 2381 | /* May need to check/upload firmware & data here! |
2219 | * If fails, continue with alt-ioc processing | 2382 | * If fails, continue with alt-ioc processing |
2220 | */ | 2383 | */ |
2384 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "SendIocInit\n", | ||
2385 | ioc->name)); | ||
2221 | if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0)) | 2386 | if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0)) |
2222 | ret = -4; | 2387 | ret = -4; |
2223 | // NEW! | 2388 | // NEW! |
2224 | if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) { | 2389 | if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) { |
2225 | printk(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n", | 2390 | printk(MYIOC_s_WARN_FMT |
2391 | ": alt-ioc (%d) FIFO mgmt alloc WARNING!\n", | ||
2226 | ioc->alt_ioc->name, rc); | 2392 | ioc->alt_ioc->name, rc); |
2227 | alt_ioc_ready = 0; | 2393 | alt_ioc_ready = 0; |
2228 | reset_alt_ioc_active = 0; | 2394 | reset_alt_ioc_active = 0; |
@@ -2232,8 +2398,9 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2232 | if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { | 2398 | if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { |
2233 | alt_ioc_ready = 0; | 2399 | alt_ioc_ready = 0; |
2234 | reset_alt_ioc_active = 0; | 2400 | reset_alt_ioc_active = 0; |
2235 | printk(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n", | 2401 | printk(MYIOC_s_WARN_FMT |
2236 | ioc->alt_ioc->name, rc); | 2402 | ": alt-ioc: (%d) init failure WARNING!\n", |
2403 | ioc->alt_ioc->name, rc); | ||
2237 | } | 2404 | } |
2238 | } | 2405 | } |
2239 | 2406 | ||
@@ -2269,28 +2436,36 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2269 | } | 2436 | } |
2270 | } | 2437 | } |
2271 | 2438 | ||
2439 | /* Enable MPT base driver management of EventNotification | ||
2440 | * and EventAck handling. | ||
2441 | */ | ||
2442 | if ((ret == 0) && (!ioc->facts.EventState)) { | ||
2443 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | ||
2444 | "SendEventNotification\n", | ||
2445 | ioc->name)); | ||
2446 | ret = SendEventNotification(ioc, 1, sleepFlag); /* 1=Enable */ | ||
2447 | } | ||
2448 | |||
2449 | if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) | ||
2450 | rc = SendEventNotification(ioc->alt_ioc, 1, sleepFlag); | ||
2451 | |||
2272 | if (ret == 0) { | 2452 | if (ret == 0) { |
2273 | /* Enable! (reply interrupt) */ | 2453 | /* Enable! (reply interrupt) */ |
2274 | CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); | 2454 | CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); |
2275 | ioc->active = 1; | 2455 | ioc->active = 1; |
2276 | } | 2456 | } |
2277 | 2457 | if (rc == 0) { /* alt ioc */ | |
2278 | if (reset_alt_ioc_active && ioc->alt_ioc) { | 2458 | if (reset_alt_ioc_active && ioc->alt_ioc) { |
2279 | /* (re)Enable alt-IOC! (reply interrupt) */ | 2459 | /* (re)Enable alt-IOC! (reply interrupt) */ |
2280 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n", | 2460 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "alt-ioc" |
2281 | ioc->alt_ioc->name)); | 2461 | "reply irq re-enabled\n", |
2282 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); | 2462 | ioc->alt_ioc->name)); |
2283 | ioc->alt_ioc->active = 1; | 2463 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, |
2464 | MPI_HIM_DIM); | ||
2465 | ioc->alt_ioc->active = 1; | ||
2466 | } | ||
2284 | } | 2467 | } |
2285 | 2468 | ||
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 | 2469 | ||
2295 | /* Add additional "reason" check before call to GetLanConfigPages | 2470 | /* Add additional "reason" check before call to GetLanConfigPages |
2296 | * (combined with GetIoUnitPage2 call). This prevents a somewhat | 2471 | * (combined with GetIoUnitPage2 call). This prevents a somewhat |
@@ -2306,8 +2481,9 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2306 | mutex_init(&ioc->raid_data.inactive_list_mutex); | 2481 | mutex_init(&ioc->raid_data.inactive_list_mutex); |
2307 | INIT_LIST_HEAD(&ioc->raid_data.inactive_list); | 2482 | INIT_LIST_HEAD(&ioc->raid_data.inactive_list); |
2308 | 2483 | ||
2309 | if (ioc->bus_type == SAS) { | 2484 | switch (ioc->bus_type) { |
2310 | 2485 | ||
2486 | case SAS: | ||
2311 | /* clear persistency table */ | 2487 | /* clear persistency table */ |
2312 | if(ioc->facts.IOCExceptions & | 2488 | if(ioc->facts.IOCExceptions & |
2313 | MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) { | 2489 | MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) { |
@@ -2321,8 +2497,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2321 | */ | 2497 | */ |
2322 | mpt_findImVolumes(ioc); | 2498 | mpt_findImVolumes(ioc); |
2323 | 2499 | ||
2324 | } else if (ioc->bus_type == FC) { | 2500 | /* Check, and possibly reset, the coalescing value |
2325 | if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && | 2501 | */ |
2502 | mpt_read_ioc_pg_1(ioc); | ||
2503 | |||
2504 | break; | ||
2505 | |||
2506 | case FC: | ||
2507 | if ((ioc->pfacts[0].ProtocolFlags & | ||
2508 | MPI_PORTFACTS_PROTOCOL_LAN) && | ||
2326 | (ioc->lan_cnfg_page0.Header.PageLength == 0)) { | 2509 | (ioc->lan_cnfg_page0.Header.PageLength == 0)) { |
2327 | /* | 2510 | /* |
2328 | * Pre-fetch the ports LAN MAC address! | 2511 | * Pre-fetch the ports LAN MAC address! |
@@ -2331,11 +2514,14 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2331 | (void) GetLanConfigPages(ioc); | 2514 | (void) GetLanConfigPages(ioc); |
2332 | a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; | 2515 | a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; |
2333 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 2516 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2334 | "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", | 2517 | "LanAddr = %02X:%02X:%02X" |
2335 | ioc->name, a[5], a[4], a[3], a[2], a[1], a[0])); | 2518 | ":%02X:%02X:%02X\n", |
2336 | 2519 | ioc->name, a[5], a[4], | |
2520 | a[3], a[2], a[1], a[0])); | ||
2337 | } | 2521 | } |
2338 | } else { | 2522 | break; |
2523 | |||
2524 | case SPI: | ||
2339 | /* Get NVRAM and adapter maximums from SPP 0 and 2 | 2525 | /* Get NVRAM and adapter maximums from SPP 0 and 2 |
2340 | */ | 2526 | */ |
2341 | mpt_GetScsiPortSettings(ioc, 0); | 2527 | mpt_GetScsiPortSettings(ioc, 0); |
@@ -2354,6 +2540,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
2354 | mpt_read_ioc_pg_1(ioc); | 2540 | mpt_read_ioc_pg_1(ioc); |
2355 | 2541 | ||
2356 | mpt_read_ioc_pg_4(ioc); | 2542 | mpt_read_ioc_pg_4(ioc); |
2543 | |||
2544 | break; | ||
2357 | } | 2545 | } |
2358 | 2546 | ||
2359 | GetIoUnitPage2(ioc); | 2547 | GetIoUnitPage2(ioc); |
@@ -2435,16 +2623,20 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) | |||
2435 | if (_pcidev == peer) { | 2623 | if (_pcidev == peer) { |
2436 | /* Paranoia checks */ | 2624 | /* Paranoia checks */ |
2437 | if (ioc->alt_ioc != NULL) { | 2625 | if (ioc->alt_ioc != NULL) { |
2438 | printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n", | 2626 | printk(MYIOC_s_WARN_FMT |
2439 | ioc->name, ioc->alt_ioc->name); | 2627 | "Oops, already bound (%s <==> %s)!\n", |
2628 | ioc->name, ioc->name, ioc->alt_ioc->name); | ||
2440 | break; | 2629 | break; |
2441 | } else if (ioc_srch->alt_ioc != NULL) { | 2630 | } else if (ioc_srch->alt_ioc != NULL) { |
2442 | printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n", | 2631 | printk(MYIOC_s_WARN_FMT |
2443 | ioc_srch->name, ioc_srch->alt_ioc->name); | 2632 | "Oops, already bound (%s <==> %s)!\n", |
2633 | ioc_srch->name, ioc_srch->name, | ||
2634 | ioc_srch->alt_ioc->name); | ||
2444 | break; | 2635 | break; |
2445 | } | 2636 | } |
2446 | dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n", | 2637 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2447 | ioc->name, ioc_srch->name)); | 2638 | "FOUND! binding %s <==> %s\n", |
2639 | ioc->name, ioc->name, ioc_srch->name)); | ||
2448 | ioc_srch->alt_ioc = ioc; | 2640 | ioc_srch->alt_ioc = ioc; |
2449 | ioc->alt_ioc = ioc_srch; | 2641 | ioc->alt_ioc = ioc_srch; |
2450 | } | 2642 | } |
@@ -2464,8 +2656,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) | |||
2464 | int ret; | 2656 | int ret; |
2465 | 2657 | ||
2466 | if (ioc->cached_fw != NULL) { | 2658 | if (ioc->cached_fw != NULL) { |
2467 | ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto " | 2659 | ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2468 | "adapter\n", __func__, ioc->name)); | 2660 | "%s: Pushing FW onto adapter\n", __func__, ioc->name)); |
2469 | if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *) | 2661 | if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *) |
2470 | ioc->cached_fw, CAN_SLEEP)) < 0) { | 2662 | ioc->cached_fw, CAN_SLEEP)) < 0) { |
2471 | printk(MYIOC_s_WARN_FMT | 2663 | printk(MYIOC_s_WARN_FMT |
@@ -2474,11 +2666,30 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) | |||
2474 | } | 2666 | } |
2475 | } | 2667 | } |
2476 | 2668 | ||
2669 | /* | ||
2670 | * Put the controller into ready state (if its not already) | ||
2671 | */ | ||
2672 | if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) { | ||
2673 | if (!SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, | ||
2674 | CAN_SLEEP)) { | ||
2675 | if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) | ||
2676 | printk(MYIOC_s_ERR_FMT "%s: IOC msg unit " | ||
2677 | "reset failed to put ioc in ready state!\n", | ||
2678 | ioc->name, __func__); | ||
2679 | } else | ||
2680 | printk(MYIOC_s_ERR_FMT "%s: IOC msg unit reset " | ||
2681 | "failed!\n", ioc->name, __func__); | ||
2682 | } | ||
2683 | |||
2684 | |||
2477 | /* Disable adapter interrupts! */ | 2685 | /* Disable adapter interrupts! */ |
2686 | synchronize_irq(ioc->pcidev->irq); | ||
2478 | CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); | 2687 | CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); |
2479 | ioc->active = 0; | 2688 | ioc->active = 0; |
2689 | |||
2480 | /* Clear any lingering interrupt */ | 2690 | /* Clear any lingering interrupt */ |
2481 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); | 2691 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); |
2692 | CHIPREG_READ32(&ioc->chip->IntStatus); | ||
2482 | 2693 | ||
2483 | if (ioc->alloc != NULL) { | 2694 | if (ioc->alloc != NULL) { |
2484 | sz = ioc->alloc_sz; | 2695 | sz = ioc->alloc_sz; |
@@ -2538,19 +2749,22 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) | |||
2538 | if((ret = mpt_host_page_access_control(ioc, | 2749 | if((ret = mpt_host_page_access_control(ioc, |
2539 | MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) { | 2750 | MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) { |
2540 | printk(MYIOC_s_ERR_FMT | 2751 | printk(MYIOC_s_ERR_FMT |
2541 | "host page buffers free failed (%d)!\n", | 2752 | ": %s: host page buffers free failed (%d)!\n", |
2542 | ioc->name, ret); | 2753 | ioc->name, __func__, ret); |
2543 | } | 2754 | } |
2544 | dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free @ %p, sz=%d bytes\n", | 2755 | dexitprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2545 | ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz)); | 2756 | "HostPageBuffer free @ %p, sz=%d bytes\n", |
2757 | ioc->name, ioc->HostPageBuffer, | ||
2758 | ioc->HostPageBuffer_sz)); | ||
2546 | pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz, | 2759 | pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz, |
2547 | ioc->HostPageBuffer, ioc->HostPageBuffer_dma); | 2760 | ioc->HostPageBuffer, ioc->HostPageBuffer_dma); |
2548 | ioc->HostPageBuffer = NULL; | 2761 | ioc->HostPageBuffer = NULL; |
2549 | ioc->HostPageBuffer_sz = 0; | 2762 | ioc->HostPageBuffer_sz = 0; |
2550 | ioc->alloc_total -= ioc->HostPageBuffer_sz; | 2763 | ioc->alloc_total -= ioc->HostPageBuffer_sz; |
2551 | } | 2764 | } |
2552 | } | ||
2553 | 2765 | ||
2766 | pci_set_drvdata(ioc->pcidev, NULL); | ||
2767 | } | ||
2554 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2768 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
2555 | /** | 2769 | /** |
2556 | * mpt_adapter_dispose - Free all resources associated with an MPT adapter | 2770 | * mpt_adapter_dispose - Free all resources associated with an MPT adapter |
@@ -2690,8 +2904,12 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) | |||
2690 | } | 2904 | } |
2691 | 2905 | ||
2692 | /* Is it already READY? */ | 2906 | /* Is it already READY? */ |
2693 | if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) | 2907 | if (!statefault && |
2908 | ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)) { | ||
2909 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT | ||
2910 | "IOC is in READY state\n", ioc->name)); | ||
2694 | return 0; | 2911 | return 0; |
2912 | } | ||
2695 | 2913 | ||
2696 | /* | 2914 | /* |
2697 | * Check to see if IOC is in FAULT state. | 2915 | * Check to see if IOC is in FAULT state. |
@@ -2764,8 +2982,9 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) | |||
2764 | 2982 | ||
2765 | ii++; cntdn--; | 2983 | ii++; cntdn--; |
2766 | if (!cntdn) { | 2984 | if (!cntdn) { |
2767 | printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n", | 2985 | printk(MYIOC_s_ERR_FMT |
2768 | ioc->name, (int)((ii+5)/HZ)); | 2986 | "Wait IOC_READY state (0x%x) timeout(%d)!\n", |
2987 | ioc->name, ioc_state, (int)((ii+5)/HZ)); | ||
2769 | return -ETIME; | 2988 | return -ETIME; |
2770 | } | 2989 | } |
2771 | 2990 | ||
@@ -2778,9 +2997,8 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) | |||
2778 | } | 2997 | } |
2779 | 2998 | ||
2780 | if (statefault < 3) { | 2999 | if (statefault < 3) { |
2781 | printk(MYIOC_s_INFO_FMT "Recovered from %s\n", | 3000 | printk(MYIOC_s_INFO_FMT "Recovered from %s\n", ioc->name, |
2782 | ioc->name, | 3001 | statefault == 1 ? "stuck handshake" : "IOC FAULT"); |
2783 | statefault==1 ? "stuck handshake" : "IOC FAULT"); | ||
2784 | } | 3002 | } |
2785 | 3003 | ||
2786 | return hard_reset_done; | 3004 | return hard_reset_done; |
@@ -2833,8 +3051,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) | |||
2833 | 3051 | ||
2834 | /* IOC *must* NOT be in RESET state! */ | 3052 | /* IOC *must* NOT be in RESET state! */ |
2835 | if (ioc->last_state == MPI_IOC_STATE_RESET) { | 3053 | if (ioc->last_state == MPI_IOC_STATE_RESET) { |
2836 | printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n", | 3054 | printk(KERN_ERR MYNAM |
2837 | ioc->name, ioc->last_state ); | 3055 | ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n", |
3056 | ioc->name, ioc->last_state); | ||
2838 | return -44; | 3057 | return -44; |
2839 | } | 3058 | } |
2840 | 3059 | ||
@@ -2896,7 +3115,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) | |||
2896 | * Old: u16{Major(4),Minor(4),SubMinor(8)} | 3115 | * Old: u16{Major(4),Minor(4),SubMinor(8)} |
2897 | * New: u32{Major(8),Minor(8),Unit(8),Dev(8)} | 3116 | * New: u32{Major(8),Minor(8),Unit(8),Dev(8)} |
2898 | */ | 3117 | */ |
2899 | if (facts->MsgVersion < 0x0102) { | 3118 | if (facts->MsgVersion < MPI_VERSION_01_02) { |
2900 | /* | 3119 | /* |
2901 | * Handle old FC f/w style, convert to new... | 3120 | * Handle old FC f/w style, convert to new... |
2902 | */ | 3121 | */ |
@@ -2908,9 +3127,11 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) | |||
2908 | facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); | 3127 | facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); |
2909 | 3128 | ||
2910 | facts->ProductID = le16_to_cpu(facts->ProductID); | 3129 | facts->ProductID = le16_to_cpu(facts->ProductID); |
3130 | |||
2911 | if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) | 3131 | if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) |
2912 | > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) | 3132 | > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) |
2913 | ioc->ir_firmware = 1; | 3133 | ioc->ir_firmware = 1; |
3134 | |||
2914 | facts->CurrentHostMfaHighAddr = | 3135 | facts->CurrentHostMfaHighAddr = |
2915 | le32_to_cpu(facts->CurrentHostMfaHighAddr); | 3136 | le32_to_cpu(facts->CurrentHostMfaHighAddr); |
2916 | facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); | 3137 | facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); |
@@ -2926,7 +3147,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) | |||
2926 | * to 14 in MPI-1.01.0x. | 3147 | * to 14 in MPI-1.01.0x. |
2927 | */ | 3148 | */ |
2928 | if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 && | 3149 | if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 && |
2929 | facts->MsgVersion > 0x0100) { | 3150 | facts->MsgVersion > MPI_VERSION_01_00) { |
2930 | facts->FWImageSize = le32_to_cpu(facts->FWImageSize); | 3151 | facts->FWImageSize = le32_to_cpu(facts->FWImageSize); |
2931 | } | 3152 | } |
2932 | 3153 | ||
@@ -3108,6 +3329,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) | |||
3108 | 3329 | ||
3109 | ioc_init.MaxDevices = (U8)ioc->devices_per_bus; | 3330 | ioc_init.MaxDevices = (U8)ioc->devices_per_bus; |
3110 | ioc_init.MaxBuses = (U8)ioc->number_of_buses; | 3331 | ioc_init.MaxBuses = (U8)ioc->number_of_buses; |
3332 | |||
3111 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n", | 3333 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n", |
3112 | ioc->name, ioc->facts.MsgVersion)); | 3334 | ioc->name, ioc->facts.MsgVersion)); |
3113 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { | 3335 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { |
@@ -3122,7 +3344,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) | |||
3122 | } | 3344 | } |
3123 | ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ | 3345 | ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ |
3124 | 3346 | ||
3125 | if (sizeof(dma_addr_t) == sizeof(u64)) { | 3347 | if (ioc->sg_addr_size == sizeof(u64)) { |
3126 | /* Save the upper 32-bits of the request | 3348 | /* Save the upper 32-bits of the request |
3127 | * (reply) and sense buffers. | 3349 | * (reply) and sense buffers. |
3128 | */ | 3350 | */ |
@@ -3325,11 +3547,10 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) | |||
3325 | FWUpload_t *prequest; | 3547 | FWUpload_t *prequest; |
3326 | FWUploadReply_t *preply; | 3548 | FWUploadReply_t *preply; |
3327 | FWUploadTCSGE_t *ptcsge; | 3549 | FWUploadTCSGE_t *ptcsge; |
3328 | int sgeoffset; | ||
3329 | u32 flagsLength; | 3550 | u32 flagsLength; |
3330 | int ii, sz, reply_sz; | 3551 | int ii, sz, reply_sz; |
3331 | int cmdStatus; | 3552 | int cmdStatus; |
3332 | 3553 | int request_size; | |
3333 | /* If the image size is 0, we are done. | 3554 | /* If the image size is 0, we are done. |
3334 | */ | 3555 | */ |
3335 | if ((sz = ioc->facts.FWImageSize) == 0) | 3556 | if ((sz = ioc->facts.FWImageSize) == 0) |
@@ -3364,42 +3585,41 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) | |||
3364 | ptcsge->ImageSize = cpu_to_le32(sz); | 3585 | ptcsge->ImageSize = cpu_to_le32(sz); |
3365 | ptcsge++; | 3586 | ptcsge++; |
3366 | 3587 | ||
3367 | sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t); | ||
3368 | |||
3369 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz; | 3588 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz; |
3370 | mpt_add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma); | 3589 | ioc->add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma); |
3371 | 3590 | request_size = offsetof(FWUpload_t, SGL) + sizeof(FWUploadTCSGE_t) + | |
3372 | sgeoffset += sizeof(u32) + sizeof(dma_addr_t); | 3591 | ioc->SGE_size; |
3373 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": Sending FW Upload (req @ %p) sgeoffset=%d \n", | 3592 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending FW Upload " |
3374 | ioc->name, prequest, sgeoffset)); | 3593 | " (req @ %p) fw_size=%d mf_request_size=%d\n", ioc->name, prequest, |
3594 | ioc->facts.FWImageSize, request_size)); | ||
3375 | DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest); | 3595 | DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest); |
3376 | 3596 | ||
3377 | ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest, | 3597 | ii = mpt_handshake_req_reply_wait(ioc, request_size, (u32 *)prequest, |
3378 | reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag); | 3598 | reply_sz, (u16 *)preply, 65 /*seconds*/, sleepFlag); |
3379 | 3599 | ||
3380 | dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii)); | 3600 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Upload completed " |
3601 | "rc=%x \n", ioc->name, ii)); | ||
3381 | 3602 | ||
3382 | cmdStatus = -EFAULT; | 3603 | cmdStatus = -EFAULT; |
3383 | if (ii == 0) { | 3604 | if (ii == 0) { |
3384 | /* Handshake transfer was complete and successful. | 3605 | /* Handshake transfer was complete and successful. |
3385 | * Check the Reply Frame. | 3606 | * Check the Reply Frame. |
3386 | */ | 3607 | */ |
3387 | int status, transfer_sz; | 3608 | int status; |
3388 | status = le16_to_cpu(preply->IOCStatus); | 3609 | status = le16_to_cpu(preply->IOCStatus) & |
3389 | if (status == MPI_IOCSTATUS_SUCCESS) { | 3610 | MPI_IOCSTATUS_MASK; |
3390 | transfer_sz = le32_to_cpu(preply->ActualImageSize); | 3611 | if (status == MPI_IOCSTATUS_SUCCESS && |
3391 | if (transfer_sz == sz) | 3612 | ioc->facts.FWImageSize == |
3613 | le32_to_cpu(preply->ActualImageSize)) | ||
3392 | cmdStatus = 0; | 3614 | cmdStatus = 0; |
3393 | } | ||
3394 | } | 3615 | } |
3395 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n", | 3616 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n", |
3396 | ioc->name, cmdStatus)); | 3617 | ioc->name, cmdStatus)); |
3397 | 3618 | ||
3398 | 3619 | ||
3399 | if (cmdStatus) { | 3620 | if (cmdStatus) { |
3400 | 3621 | ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed, " | |
3401 | ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": fw upload failed, freeing image \n", | 3622 | "freeing image \n", ioc->name)); |
3402 | ioc->name)); | ||
3403 | mpt_free_fw_memory(ioc); | 3623 | mpt_free_fw_memory(ioc); |
3404 | } | 3624 | } |
3405 | kfree(prequest); | 3625 | kfree(prequest); |
@@ -3723,6 +3943,10 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
3723 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); | 3943 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); |
3724 | 3944 | ||
3725 | if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { | 3945 | if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { |
3946 | |||
3947 | if (!ignore) | ||
3948 | return 0; | ||
3949 | |||
3726 | drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " | 3950 | drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " |
3727 | "address=%p\n", ioc->name, __func__, | 3951 | "address=%p\n", ioc->name, __func__, |
3728 | &ioc->chip->Doorbell, &ioc->chip->Reset_1078)); | 3952 | &ioc->chip->Doorbell, &ioc->chip->Reset_1078)); |
@@ -3740,6 +3964,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
3740 | "looking for READY STATE: doorbell=%x" | 3964 | "looking for READY STATE: doorbell=%x" |
3741 | " count=%d\n", | 3965 | " count=%d\n", |
3742 | ioc->name, doorbell, count)); | 3966 | ioc->name, doorbell, count)); |
3967 | |||
3743 | if (doorbell == MPI_IOC_STATE_READY) { | 3968 | if (doorbell == MPI_IOC_STATE_READY) { |
3744 | return 1; | 3969 | return 1; |
3745 | } | 3970 | } |
@@ -3890,6 +4115,10 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
3890 | doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); | 4115 | doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); |
3891 | doorbell &= MPI_IOC_STATE_MASK; | 4116 | doorbell &= MPI_IOC_STATE_MASK; |
3892 | 4117 | ||
4118 | drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
4119 | "looking for READY STATE: doorbell=%x" | ||
4120 | " count=%d\n", ioc->name, doorbell, count)); | ||
4121 | |||
3893 | if (doorbell == MPI_IOC_STATE_READY) { | 4122 | if (doorbell == MPI_IOC_STATE_READY) { |
3894 | break; | 4123 | break; |
3895 | } | 4124 | } |
@@ -3901,6 +4130,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
3901 | mdelay (1000); | 4130 | mdelay (1000); |
3902 | } | 4131 | } |
3903 | } | 4132 | } |
4133 | |||
4134 | if (doorbell != MPI_IOC_STATE_READY) | ||
4135 | printk(MYIOC_s_ERR_FMT "Failed to come READY " | ||
4136 | "after reset! IocState=%x", ioc->name, | ||
4137 | doorbell); | ||
3904 | } | 4138 | } |
3905 | } | 4139 | } |
3906 | 4140 | ||
@@ -4019,8 +4253,9 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) | |||
4019 | if (sleepFlag != CAN_SLEEP) | 4253 | if (sleepFlag != CAN_SLEEP) |
4020 | count *= 10; | 4254 | count *= 10; |
4021 | 4255 | ||
4022 | printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n", | 4256 | printk(MYIOC_s_ERR_FMT |
4023 | ioc->name, (int)((count+5)/HZ)); | 4257 | "Wait IOC_READY state (0x%x) timeout(%d)!\n", |
4258 | ioc->name, state, (int)((count+5)/HZ)); | ||
4024 | return -ETIME; | 4259 | return -ETIME; |
4025 | } | 4260 | } |
4026 | 4261 | ||
@@ -4090,24 +4325,29 @@ initChainBuffers(MPT_ADAPTER *ioc) | |||
4090 | * num_sge = num sge in request frame + last chain buffer | 4325 | * num_sge = num sge in request frame + last chain buffer |
4091 | * scale = num sge per chain buffer if no chain element | 4326 | * scale = num sge per chain buffer if no chain element |
4092 | */ | 4327 | */ |
4093 | scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); | 4328 | scale = ioc->req_sz / ioc->SGE_size; |
4094 | if (sizeof(dma_addr_t) == sizeof(u64)) | 4329 | if (ioc->sg_addr_size == sizeof(u64)) |
4095 | num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32)); | 4330 | num_sge = scale + (ioc->req_sz - 60) / ioc->SGE_size; |
4096 | else | 4331 | else |
4097 | num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); | 4332 | num_sge = 1 + scale + (ioc->req_sz - 64) / ioc->SGE_size; |
4098 | 4333 | ||
4099 | if (sizeof(dma_addr_t) == sizeof(u64)) { | 4334 | if (ioc->sg_addr_size == sizeof(u64)) { |
4100 | numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + | 4335 | numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + |
4101 | (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32)); | 4336 | (ioc->req_sz - 60) / ioc->SGE_size; |
4102 | } else { | 4337 | } else { |
4103 | numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + | 4338 | numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + |
4104 | (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); | 4339 | scale + (ioc->req_sz - 64) / ioc->SGE_size; |
4105 | } | 4340 | } |
4106 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n", | 4341 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n", |
4107 | ioc->name, num_sge, numSGE)); | 4342 | ioc->name, num_sge, numSGE)); |
4108 | 4343 | ||
4109 | if ( numSGE > MPT_SCSI_SG_DEPTH ) | 4344 | if (ioc->bus_type == FC) { |
4110 | numSGE = MPT_SCSI_SG_DEPTH; | 4345 | if (numSGE > MPT_SCSI_FC_SG_DEPTH) |
4346 | numSGE = MPT_SCSI_FC_SG_DEPTH; | ||
4347 | } else { | ||
4348 | if (numSGE > MPT_SCSI_SG_DEPTH) | ||
4349 | numSGE = MPT_SCSI_SG_DEPTH; | ||
4350 | } | ||
4111 | 4351 | ||
4112 | num_chain = 1; | 4352 | num_chain = 1; |
4113 | while (numSGE - num_sge > 0) { | 4353 | while (numSGE - num_sge > 0) { |
@@ -4161,12 +4401,42 @@ PrimeIocFifos(MPT_ADAPTER *ioc) | |||
4161 | dma_addr_t alloc_dma; | 4401 | dma_addr_t alloc_dma; |
4162 | u8 *mem; | 4402 | u8 *mem; |
4163 | int i, reply_sz, sz, total_size, num_chain; | 4403 | int i, reply_sz, sz, total_size, num_chain; |
4404 | u64 dma_mask; | ||
4405 | |||
4406 | dma_mask = 0; | ||
4164 | 4407 | ||
4165 | /* Prime reply FIFO... */ | 4408 | /* Prime reply FIFO... */ |
4166 | 4409 | ||
4167 | if (ioc->reply_frames == NULL) { | 4410 | if (ioc->reply_frames == NULL) { |
4168 | if ( (num_chain = initChainBuffers(ioc)) < 0) | 4411 | if ( (num_chain = initChainBuffers(ioc)) < 0) |
4169 | return -1; | 4412 | return -1; |
4413 | /* | ||
4414 | * 1078 errata workaround for the 36GB limitation | ||
4415 | */ | ||
4416 | if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078 && | ||
4417 | ioc->dma_mask > DMA_35BIT_MASK) { | ||
4418 | if (!pci_set_dma_mask(ioc->pcidev, DMA_BIT_MASK(32)) | ||
4419 | && !pci_set_consistent_dma_mask(ioc->pcidev, | ||
4420 | DMA_BIT_MASK(32))) { | ||
4421 | dma_mask = DMA_35BIT_MASK; | ||
4422 | d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
4423 | "setting 35 bit addressing for " | ||
4424 | "Request/Reply/Chain and Sense Buffers\n", | ||
4425 | ioc->name)); | ||
4426 | } else { | ||
4427 | /*Reseting DMA mask to 64 bit*/ | ||
4428 | pci_set_dma_mask(ioc->pcidev, | ||
4429 | DMA_BIT_MASK(64)); | ||
4430 | pci_set_consistent_dma_mask(ioc->pcidev, | ||
4431 | DMA_BIT_MASK(64)); | ||
4432 | |||
4433 | printk(MYIOC_s_ERR_FMT | ||
4434 | "failed setting 35 bit addressing for " | ||
4435 | "Request/Reply/Chain and Sense Buffers\n", | ||
4436 | ioc->name); | ||
4437 | return -1; | ||
4438 | } | ||
4439 | } | ||
4170 | 4440 | ||
4171 | total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth); | 4441 | 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", | 4442 | dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n", |
@@ -4305,9 +4575,16 @@ PrimeIocFifos(MPT_ADAPTER *ioc) | |||
4305 | alloc_dma += ioc->reply_sz; | 4575 | alloc_dma += ioc->reply_sz; |
4306 | } | 4576 | } |
4307 | 4577 | ||
4578 | if (dma_mask == DMA_35BIT_MASK && !pci_set_dma_mask(ioc->pcidev, | ||
4579 | ioc->dma_mask) && !pci_set_consistent_dma_mask(ioc->pcidev, | ||
4580 | ioc->dma_mask)) | ||
4581 | d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
4582 | "restoring 64 bit addressing\n", ioc->name)); | ||
4583 | |||
4308 | return 0; | 4584 | return 0; |
4309 | 4585 | ||
4310 | out_fail: | 4586 | out_fail: |
4587 | |||
4311 | if (ioc->alloc != NULL) { | 4588 | if (ioc->alloc != NULL) { |
4312 | sz = ioc->alloc_sz; | 4589 | sz = ioc->alloc_sz; |
4313 | pci_free_consistent(ioc->pcidev, | 4590 | pci_free_consistent(ioc->pcidev, |
@@ -4324,6 +4601,13 @@ out_fail: | |||
4324 | ioc->sense_buf_pool, ioc->sense_buf_pool_dma); | 4601 | ioc->sense_buf_pool, ioc->sense_buf_pool_dma); |
4325 | ioc->sense_buf_pool = NULL; | 4602 | ioc->sense_buf_pool = NULL; |
4326 | } | 4603 | } |
4604 | |||
4605 | if (dma_mask == DMA_35BIT_MASK && !pci_set_dma_mask(ioc->pcidev, | ||
4606 | DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(ioc->pcidev, | ||
4607 | DMA_BIT_MASK(64))) | ||
4608 | d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
4609 | "restoring 64 bit addressing\n", ioc->name)); | ||
4610 | |||
4327 | return -1; | 4611 | return -1; |
4328 | } | 4612 | } |
4329 | 4613 | ||
@@ -4759,7 +5043,14 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) | |||
4759 | SasIoUnitControlReply_t *sasIoUnitCntrReply; | 5043 | SasIoUnitControlReply_t *sasIoUnitCntrReply; |
4760 | MPT_FRAME_HDR *mf = NULL; | 5044 | MPT_FRAME_HDR *mf = NULL; |
4761 | MPIHeader_t *mpi_hdr; | 5045 | MPIHeader_t *mpi_hdr; |
5046 | int ret = 0; | ||
5047 | unsigned long timeleft; | ||
5048 | |||
5049 | mutex_lock(&ioc->mptbase_cmds.mutex); | ||
4762 | 5050 | ||
5051 | /* init the internal cmd struct */ | ||
5052 | memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE); | ||
5053 | INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status) | ||
4763 | 5054 | ||
4764 | /* insure garbage is not sent to fw */ | 5055 | /* insure garbage is not sent to fw */ |
4765 | switch(persist_opcode) { | 5056 | switch(persist_opcode) { |
@@ -4769,17 +5060,19 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) | |||
4769 | break; | 5060 | break; |
4770 | 5061 | ||
4771 | default: | 5062 | default: |
4772 | return -1; | 5063 | ret = -1; |
4773 | break; | 5064 | goto out; |
4774 | } | 5065 | } |
4775 | 5066 | ||
4776 | printk("%s: persist_opcode=%x\n",__func__, persist_opcode); | 5067 | printk(KERN_DEBUG "%s: persist_opcode=%x\n", |
5068 | __func__, persist_opcode); | ||
4777 | 5069 | ||
4778 | /* Get a MF for this command. | 5070 | /* Get a MF for this command. |
4779 | */ | 5071 | */ |
4780 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { | 5072 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { |
4781 | printk("%s: no msg frames!\n",__func__); | 5073 | printk(KERN_DEBUG "%s: no msg frames!\n", __func__); |
4782 | return -1; | 5074 | ret = -1; |
5075 | goto out; | ||
4783 | } | 5076 | } |
4784 | 5077 | ||
4785 | mpi_hdr = (MPIHeader_t *) mf; | 5078 | mpi_hdr = (MPIHeader_t *) mf; |
@@ -4789,27 +5082,42 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) | |||
4789 | sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; | 5082 | sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; |
4790 | sasIoUnitCntrReq->Operation = persist_opcode; | 5083 | sasIoUnitCntrReq->Operation = persist_opcode; |
4791 | 5084 | ||
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); | 5085 | mpt_put_msg_frame(mpt_base_index, ioc, mf); |
4799 | wait_event(mpt_waitq, ioc->persist_wait_done); | 5086 | timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, 10*HZ); |
5087 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | ||
5088 | ret = -ETIME; | ||
5089 | printk(KERN_DEBUG "%s: failed\n", __func__); | ||
5090 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) | ||
5091 | goto out; | ||
5092 | if (!timeleft) { | ||
5093 | printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n", | ||
5094 | ioc->name, __func__); | ||
5095 | mpt_HardResetHandler(ioc, CAN_SLEEP); | ||
5096 | mpt_free_msg_frame(ioc, mf); | ||
5097 | } | ||
5098 | goto out; | ||
5099 | } | ||
5100 | |||
5101 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { | ||
5102 | ret = -1; | ||
5103 | goto out; | ||
5104 | } | ||
4800 | 5105 | ||
4801 | sasIoUnitCntrReply = | 5106 | sasIoUnitCntrReply = |
4802 | (SasIoUnitControlReply_t *)ioc->persist_reply_frame; | 5107 | (SasIoUnitControlReply_t *)ioc->mptbase_cmds.reply; |
4803 | if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) { | 5108 | if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) { |
4804 | printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", | 5109 | printk(KERN_DEBUG "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", |
4805 | __func__, | 5110 | __func__, sasIoUnitCntrReply->IOCStatus, |
4806 | sasIoUnitCntrReply->IOCStatus, | ||
4807 | sasIoUnitCntrReply->IOCLogInfo); | 5111 | sasIoUnitCntrReply->IOCLogInfo); |
4808 | return -1; | 5112 | printk(KERN_DEBUG "%s: failed\n", __func__); |
4809 | } | 5113 | ret = -1; |
5114 | } else | ||
5115 | printk(KERN_DEBUG "%s: success\n", __func__); | ||
5116 | out: | ||
4810 | 5117 | ||
4811 | printk("%s: success\n",__func__); | 5118 | CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status) |
4812 | return 0; | 5119 | mutex_unlock(&ioc->mptbase_cmds.mutex); |
5120 | return ret; | ||
4813 | } | 5121 | } |
4814 | 5122 | ||
4815 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 5123 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -5394,17 +5702,20 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
5394 | * -ENOMEM if pci_alloc failed | 5702 | * -ENOMEM if pci_alloc failed |
5395 | **/ | 5703 | **/ |
5396 | int | 5704 | int |
5397 | mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk) | 5705 | mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, |
5706 | RaidPhysDiskPage0_t *phys_disk) | ||
5398 | { | 5707 | { |
5399 | CONFIGPARMS cfg; | 5708 | CONFIGPARMS cfg; |
5400 | ConfigPageHeader_t hdr; | 5709 | ConfigPageHeader_t hdr; |
5401 | dma_addr_t dma_handle; | 5710 | dma_addr_t dma_handle; |
5402 | pRaidPhysDiskPage0_t buffer = NULL; | 5711 | pRaidPhysDiskPage0_t buffer = NULL; |
5403 | int rc; | 5712 | int rc; |
5404 | 5713 | ||
5405 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | 5714 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); |
5406 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | 5715 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); |
5716 | memset(phys_disk, 0, sizeof(RaidPhysDiskPage0_t)); | ||
5407 | 5717 | ||
5718 | hdr.PageVersion = MPI_RAIDPHYSDISKPAGE0_PAGEVERSION; | ||
5408 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; | 5719 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; |
5409 | cfg.cfghdr.hdr = &hdr; | 5720 | cfg.cfghdr.hdr = &hdr; |
5410 | cfg.physAddr = -1; | 5721 | cfg.physAddr = -1; |
@@ -5451,6 +5762,161 @@ mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t | |||
5451 | } | 5762 | } |
5452 | 5763 | ||
5453 | /** | 5764 | /** |
5765 | * mpt_raid_phys_disk_get_num_paths - returns number paths associated to this phys_num | ||
5766 | * @ioc: Pointer to a Adapter Structure | ||
5767 | * @phys_disk_num: io unit unique phys disk num generated by the ioc | ||
5768 | * | ||
5769 | * Return: | ||
5770 | * returns number paths | ||
5771 | **/ | ||
5772 | int | ||
5773 | mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num) | ||
5774 | { | ||
5775 | CONFIGPARMS cfg; | ||
5776 | ConfigPageHeader_t hdr; | ||
5777 | dma_addr_t dma_handle; | ||
5778 | pRaidPhysDiskPage1_t buffer = NULL; | ||
5779 | int rc; | ||
5780 | |||
5781 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
5782 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
5783 | |||
5784 | hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION; | ||
5785 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; | ||
5786 | hdr.PageNumber = 1; | ||
5787 | cfg.cfghdr.hdr = &hdr; | ||
5788 | cfg.physAddr = -1; | ||
5789 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
5790 | |||
5791 | if (mpt_config(ioc, &cfg) != 0) { | ||
5792 | rc = 0; | ||
5793 | goto out; | ||
5794 | } | ||
5795 | |||
5796 | if (!hdr.PageLength) { | ||
5797 | rc = 0; | ||
5798 | goto out; | ||
5799 | } | ||
5800 | |||
5801 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
5802 | &dma_handle); | ||
5803 | |||
5804 | if (!buffer) { | ||
5805 | rc = 0; | ||
5806 | goto out; | ||
5807 | } | ||
5808 | |||
5809 | cfg.physAddr = dma_handle; | ||
5810 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
5811 | cfg.pageAddr = phys_disk_num; | ||
5812 | |||
5813 | if (mpt_config(ioc, &cfg) != 0) { | ||
5814 | rc = 0; | ||
5815 | goto out; | ||
5816 | } | ||
5817 | |||
5818 | rc = buffer->NumPhysDiskPaths; | ||
5819 | out: | ||
5820 | |||
5821 | if (buffer) | ||
5822 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
5823 | dma_handle); | ||
5824 | |||
5825 | return rc; | ||
5826 | } | ||
5827 | EXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths); | ||
5828 | |||
5829 | /** | ||
5830 | * mpt_raid_phys_disk_pg1 - returns phys disk page 1 | ||
5831 | * @ioc: Pointer to a Adapter Structure | ||
5832 | * @phys_disk_num: io unit unique phys disk num generated by the ioc | ||
5833 | * @phys_disk: requested payload data returned | ||
5834 | * | ||
5835 | * Return: | ||
5836 | * 0 on success | ||
5837 | * -EFAULT if read of config page header fails or data pointer not NULL | ||
5838 | * -ENOMEM if pci_alloc failed | ||
5839 | **/ | ||
5840 | int | ||
5841 | mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num, | ||
5842 | RaidPhysDiskPage1_t *phys_disk) | ||
5843 | { | ||
5844 | CONFIGPARMS cfg; | ||
5845 | ConfigPageHeader_t hdr; | ||
5846 | dma_addr_t dma_handle; | ||
5847 | pRaidPhysDiskPage1_t buffer = NULL; | ||
5848 | int rc; | ||
5849 | int i; | ||
5850 | __le64 sas_address; | ||
5851 | |||
5852 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
5853 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
5854 | rc = 0; | ||
5855 | |||
5856 | hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION; | ||
5857 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; | ||
5858 | hdr.PageNumber = 1; | ||
5859 | cfg.cfghdr.hdr = &hdr; | ||
5860 | cfg.physAddr = -1; | ||
5861 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
5862 | |||
5863 | if (mpt_config(ioc, &cfg) != 0) { | ||
5864 | rc = -EFAULT; | ||
5865 | goto out; | ||
5866 | } | ||
5867 | |||
5868 | if (!hdr.PageLength) { | ||
5869 | rc = -EFAULT; | ||
5870 | goto out; | ||
5871 | } | ||
5872 | |||
5873 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
5874 | &dma_handle); | ||
5875 | |||
5876 | if (!buffer) { | ||
5877 | rc = -ENOMEM; | ||
5878 | goto out; | ||
5879 | } | ||
5880 | |||
5881 | cfg.physAddr = dma_handle; | ||
5882 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
5883 | cfg.pageAddr = phys_disk_num; | ||
5884 | |||
5885 | if (mpt_config(ioc, &cfg) != 0) { | ||
5886 | rc = -EFAULT; | ||
5887 | goto out; | ||
5888 | } | ||
5889 | |||
5890 | phys_disk->NumPhysDiskPaths = buffer->NumPhysDiskPaths; | ||
5891 | phys_disk->PhysDiskNum = phys_disk_num; | ||
5892 | for (i = 0; i < phys_disk->NumPhysDiskPaths; i++) { | ||
5893 | phys_disk->Path[i].PhysDiskID = buffer->Path[i].PhysDiskID; | ||
5894 | phys_disk->Path[i].PhysDiskBus = buffer->Path[i].PhysDiskBus; | ||
5895 | phys_disk->Path[i].OwnerIdentifier = | ||
5896 | buffer->Path[i].OwnerIdentifier; | ||
5897 | phys_disk->Path[i].Flags = le16_to_cpu(buffer->Path[i].Flags); | ||
5898 | memcpy(&sas_address, &buffer->Path[i].WWID, sizeof(__le64)); | ||
5899 | sas_address = le64_to_cpu(sas_address); | ||
5900 | memcpy(&phys_disk->Path[i].WWID, &sas_address, sizeof(__le64)); | ||
5901 | memcpy(&sas_address, | ||
5902 | &buffer->Path[i].OwnerWWID, sizeof(__le64)); | ||
5903 | sas_address = le64_to_cpu(sas_address); | ||
5904 | memcpy(&phys_disk->Path[i].OwnerWWID, | ||
5905 | &sas_address, sizeof(__le64)); | ||
5906 | } | ||
5907 | |||
5908 | out: | ||
5909 | |||
5910 | if (buffer) | ||
5911 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
5912 | dma_handle); | ||
5913 | |||
5914 | return rc; | ||
5915 | } | ||
5916 | EXPORT_SYMBOL(mpt_raid_phys_disk_pg1); | ||
5917 | |||
5918 | |||
5919 | /** | ||
5454 | * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes | 5920 | * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes |
5455 | * @ioc: Pointer to a Adapter Strucutre | 5921 | * @ioc: Pointer to a Adapter Strucutre |
5456 | * | 5922 | * |
@@ -5775,30 +6241,28 @@ mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc) | |||
5775 | * SendEventNotification - Send EventNotification (on or off) request to adapter | 6241 | * SendEventNotification - Send EventNotification (on or off) request to adapter |
5776 | * @ioc: Pointer to MPT_ADAPTER structure | 6242 | * @ioc: Pointer to MPT_ADAPTER structure |
5777 | * @EvSwitch: Event switch flags | 6243 | * @EvSwitch: Event switch flags |
6244 | * @sleepFlag: Specifies whether the process can sleep | ||
5778 | */ | 6245 | */ |
5779 | static int | 6246 | static int |
5780 | SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch) | 6247 | SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, int sleepFlag) |
5781 | { | 6248 | { |
5782 | EventNotification_t *evnp; | 6249 | EventNotification_t evn; |
6250 | MPIDefaultReply_t reply_buf; | ||
5783 | 6251 | ||
5784 | evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc); | 6252 | memset(&evn, 0, sizeof(EventNotification_t)); |
5785 | if (evnp == NULL) { | 6253 | 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 | 6254 | ||
5794 | evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; | 6255 | evn.Function = MPI_FUNCTION_EVENT_NOTIFICATION; |
5795 | evnp->ChainOffset = 0; | 6256 | evn.Switch = EvSwitch; |
5796 | evnp->MsgFlags = 0; | 6257 | evn.MsgContext = cpu_to_le32(mpt_base_index << 16); |
5797 | evnp->Switch = EvSwitch; | ||
5798 | 6258 | ||
5799 | mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp); | 6259 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
6260 | "Sending EventNotification (%d) request %p\n", | ||
6261 | ioc->name, EvSwitch, &evn)); | ||
5800 | 6262 | ||
5801 | return 0; | 6263 | return mpt_handshake_req_reply_wait(ioc, sizeof(EventNotification_t), |
6264 | (u32 *)&evn, sizeof(MPIDefaultReply_t), (u16 *)&reply_buf, 30, | ||
6265 | sleepFlag); | ||
5802 | } | 6266 | } |
5803 | 6267 | ||
5804 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6268 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -5814,7 +6278,7 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) | |||
5814 | 6278 | ||
5815 | if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { | 6279 | 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", | 6280 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n", |
5817 | ioc->name,__func__)); | 6281 | ioc->name, __func__)); |
5818 | return -1; | 6282 | return -1; |
5819 | } | 6283 | } |
5820 | 6284 | ||
@@ -5851,12 +6315,19 @@ int | |||
5851 | mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | 6315 | mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) |
5852 | { | 6316 | { |
5853 | Config_t *pReq; | 6317 | Config_t *pReq; |
6318 | ConfigReply_t *pReply; | ||
5854 | ConfigExtendedPageHeader_t *pExtHdr = NULL; | 6319 | ConfigExtendedPageHeader_t *pExtHdr = NULL; |
5855 | MPT_FRAME_HDR *mf; | 6320 | MPT_FRAME_HDR *mf; |
5856 | unsigned long flags; | 6321 | int ii; |
5857 | int ii, rc; | ||
5858 | int flagsLength; | 6322 | int flagsLength; |
5859 | int in_isr; | 6323 | long timeout; |
6324 | int ret; | ||
6325 | u8 page_type = 0, extend_page; | ||
6326 | unsigned long timeleft; | ||
6327 | unsigned long flags; | ||
6328 | int in_isr; | ||
6329 | u8 issue_hard_reset = 0; | ||
6330 | u8 retry_count = 0; | ||
5860 | 6331 | ||
5861 | /* Prevent calling wait_event() (below), if caller happens | 6332 | /* Prevent calling wait_event() (below), if caller happens |
5862 | * to be in ISR context, because that is fatal! | 6333 | * to be in ISR context, because that is fatal! |
@@ -5866,15 +6337,43 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | |||
5866 | dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n", | 6337 | dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n", |
5867 | ioc->name)); | 6338 | ioc->name)); |
5868 | return -EPERM; | 6339 | return -EPERM; |
6340 | } | ||
6341 | |||
6342 | /* don't send a config page during diag reset */ | ||
6343 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
6344 | if (ioc->ioc_reset_in_progress) { | ||
6345 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
6346 | "%s: busy with host reset\n", ioc->name, __func__)); | ||
6347 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
6348 | return -EBUSY; | ||
6349 | } | ||
6350 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
6351 | |||
6352 | /* don't send if no chance of success */ | ||
6353 | if (!ioc->active || | ||
6354 | mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_OPERATIONAL) { | ||
6355 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
6356 | "%s: ioc not operational, %d, %xh\n", | ||
6357 | ioc->name, __func__, ioc->active, | ||
6358 | mpt_GetIocState(ioc, 0))); | ||
6359 | return -EFAULT; | ||
5869 | } | 6360 | } |
5870 | 6361 | ||
6362 | retry_config: | ||
6363 | mutex_lock(&ioc->mptbase_cmds.mutex); | ||
6364 | /* init the internal cmd struct */ | ||
6365 | memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE); | ||
6366 | INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status) | ||
6367 | |||
5871 | /* Get and Populate a free Frame | 6368 | /* Get and Populate a free Frame |
5872 | */ | 6369 | */ |
5873 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { | 6370 | 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", | 6371 | dcprintk(ioc, printk(MYIOC_s_WARN_FMT |
5875 | ioc->name)); | 6372 | "mpt_config: no msg frames!\n", ioc->name)); |
5876 | return -EAGAIN; | 6373 | ret = -EAGAIN; |
6374 | goto out; | ||
5877 | } | 6375 | } |
6376 | |||
5878 | pReq = (Config_t *)mf; | 6377 | pReq = (Config_t *)mf; |
5879 | pReq->Action = pCfg->action; | 6378 | pReq->Action = pCfg->action; |
5880 | pReq->Reserved = 0; | 6379 | pReq->Reserved = 0; |
@@ -5900,7 +6399,9 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | |||
5900 | pReq->ExtPageType = pExtHdr->ExtPageType; | 6399 | pReq->ExtPageType = pExtHdr->ExtPageType; |
5901 | pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; | 6400 | pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; |
5902 | 6401 | ||
5903 | /* Page Length must be treated as a reserved field for the extended header. */ | 6402 | /* Page Length must be treated as a reserved field for the |
6403 | * extended header. | ||
6404 | */ | ||
5904 | pReq->Header.PageLength = 0; | 6405 | pReq->Header.PageLength = 0; |
5905 | } | 6406 | } |
5906 | 6407 | ||
@@ -5913,78 +6414,91 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | |||
5913 | else | 6414 | else |
5914 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; | 6415 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; |
5915 | 6416 | ||
5916 | if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) { | 6417 | if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == |
6418 | MPI_CONFIG_PAGETYPE_EXTENDED) { | ||
5917 | flagsLength |= pExtHdr->ExtPageLength * 4; | 6419 | flagsLength |= pExtHdr->ExtPageLength * 4; |
5918 | 6420 | page_type = pReq->ExtPageType; | |
5919 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n", | 6421 | extend_page = 1; |
5920 | ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action)); | 6422 | } else { |
5921 | } | ||
5922 | else { | ||
5923 | flagsLength |= pCfg->cfghdr.hdr->PageLength * 4; | 6423 | flagsLength |= pCfg->cfghdr.hdr->PageLength * 4; |
5924 | 6424 | page_type = pReq->Header.PageType; | |
5925 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n", | 6425 | extend_page = 0; |
5926 | ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action)); | ||
5927 | } | 6426 | } |
5928 | 6427 | ||
5929 | mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr); | 6428 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
5930 | 6429 | "Sending Config request type 0x%x, page 0x%x and action %d\n", | |
5931 | /* Append pCfg pointer to end of mf | 6430 | 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 | 6431 | ||
5953 | add_timer(&pCfg->timer); | 6432 | ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr); |
6433 | timeout = (pCfg->timeout < 15) ? HZ*15 : HZ*pCfg->timeout; | ||
5954 | mpt_put_msg_frame(mpt_base_index, ioc, mf); | 6434 | mpt_put_msg_frame(mpt_base_index, ioc, mf); |
5955 | wait_event(mpt_waitq, pCfg->wait_done); | 6435 | timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, |
6436 | timeout); | ||
6437 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | ||
6438 | ret = -ETIME; | ||
6439 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
6440 | "Failed Sending Config request type 0x%x, page 0x%x," | ||
6441 | " action %d, status %xh, time left %ld\n\n", | ||
6442 | ioc->name, page_type, pReq->Header.PageNumber, | ||
6443 | pReq->Action, ioc->mptbase_cmds.status, timeleft)); | ||
6444 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) | ||
6445 | goto out; | ||
6446 | if (!timeleft) | ||
6447 | issue_hard_reset = 1; | ||
6448 | goto out; | ||
6449 | } | ||
5956 | 6450 | ||
5957 | /* mf has been freed - do not access */ | 6451 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { |
6452 | ret = -1; | ||
6453 | goto out; | ||
6454 | } | ||
6455 | pReply = (ConfigReply_t *)ioc->mptbase_cmds.reply; | ||
6456 | ret = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
6457 | if (ret == MPI_IOCSTATUS_SUCCESS) { | ||
6458 | if (extend_page) { | ||
6459 | pCfg->cfghdr.ehdr->ExtPageLength = | ||
6460 | le16_to_cpu(pReply->ExtPageLength); | ||
6461 | pCfg->cfghdr.ehdr->ExtPageType = | ||
6462 | pReply->ExtPageType; | ||
6463 | } | ||
6464 | pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion; | ||
6465 | pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength; | ||
6466 | pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber; | ||
6467 | pCfg->cfghdr.hdr->PageType = pReply->Header.PageType; | ||
5958 | 6468 | ||
5959 | rc = pCfg->status; | 6469 | } |
5960 | 6470 | ||
5961 | return rc; | 6471 | if (retry_count) |
5962 | } | 6472 | printk(MYIOC_s_INFO_FMT "Retry completed " |
6473 | "ret=0x%x timeleft=%ld\n", | ||
6474 | ioc->name, ret, timeleft); | ||
5963 | 6475 | ||
5964 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6476 | dcprintk(ioc, printk(KERN_DEBUG "IOCStatus=%04xh, IOCLogInfo=%08xh\n", |
5965 | /** | 6477 | 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 | 6478 | ||
5977 | /* Perform a FW reload */ | 6479 | out: |
5978 | if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) | ||
5979 | printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name); | ||
5980 | 6480 | ||
5981 | /* No more processing. | 6481 | CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status) |
5982 | * Hard reset clean-up will wake up | 6482 | mutex_unlock(&ioc->mptbase_cmds.mutex); |
5983 | * process and free all resources. | 6483 | if (issue_hard_reset) { |
5984 | */ | 6484 | issue_hard_reset = 0; |
5985 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired complete!\n", ioc->name)); | 6485 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", |
6486 | ioc->name, __func__); | ||
6487 | mpt_HardResetHandler(ioc, CAN_SLEEP); | ||
6488 | mpt_free_msg_frame(ioc, mf); | ||
6489 | /* attempt one retry for a timed out command */ | ||
6490 | if (!retry_count) { | ||
6491 | printk(MYIOC_s_INFO_FMT | ||
6492 | "Attempting Retry Config request" | ||
6493 | " type 0x%x, page 0x%x," | ||
6494 | " action %d\n", ioc->name, page_type, | ||
6495 | pCfg->cfghdr.hdr->PageNumber, pCfg->action); | ||
6496 | retry_count++; | ||
6497 | goto retry_config; | ||
6498 | } | ||
6499 | } | ||
6500 | return ret; | ||
5986 | 6501 | ||
5987 | return; | ||
5988 | } | 6502 | } |
5989 | 6503 | ||
5990 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6504 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -5998,41 +6512,34 @@ mpt_timer_expired(unsigned long data) | |||
5998 | static int | 6512 | static int |
5999 | mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | 6513 | mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) |
6000 | { | 6514 | { |
6001 | CONFIGPARMS *pCfg; | 6515 | switch (reset_phase) { |
6002 | unsigned long flags; | 6516 | case MPT_IOC_SETUP_RESET: |
6003 | 6517 | ioc->taskmgmt_quiesce_io = 1; | |
6004 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 6518 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
6005 | ": IOC %s_reset routed to MPT base driver!\n", | 6519 | "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__)); |
6006 | ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( | 6520 | break; |
6007 | reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); | 6521 | case MPT_IOC_PRE_RESET: |
6008 | 6522 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | |
6009 | if (reset_phase == MPT_IOC_SETUP_RESET) { | 6523 | "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__)); |
6010 | ; | 6524 | break; |
6011 | } else if (reset_phase == MPT_IOC_PRE_RESET) { | 6525 | case MPT_IOC_POST_RESET: |
6012 | /* If the internal config Q is not empty - | 6526 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
6013 | * delete timer. MF resources will be freed when | 6527 | "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__)); |
6014 | * the FIFO's are primed. | 6528 | /* wake up mptbase_cmds */ |
6015 | */ | 6529 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) { |
6016 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 6530 | ioc->mptbase_cmds.status |= |
6017 | list_for_each_entry(pCfg, &ioc->configQ, linkage) | 6531 | MPT_MGMT_STATUS_DID_IOCRESET; |
6018 | del_timer(&pCfg->timer); | 6532 | 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 | } | 6533 | } |
6035 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 6534 | /* wake up taskmgmt_cmds */ |
6535 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) { | ||
6536 | ioc->taskmgmt_cmds.status |= | ||
6537 | MPT_MGMT_STATUS_DID_IOCRESET; | ||
6538 | complete(&ioc->taskmgmt_cmds.done); | ||
6539 | } | ||
6540 | break; | ||
6541 | default: | ||
6542 | break; | ||
6036 | } | 6543 | } |
6037 | 6544 | ||
6038 | return 1; /* currently means nothing really */ | 6545 | return 1; /* currently means nothing really */ |
@@ -6344,6 +6851,59 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh | |||
6344 | 6851 | ||
6345 | *size = y; | 6852 | *size = y; |
6346 | } | 6853 | } |
6854 | /** | ||
6855 | * mpt_set_taskmgmt_in_progress_flag - set flags associated with task managment | ||
6856 | * @ioc: Pointer to MPT_ADAPTER structure | ||
6857 | * | ||
6858 | * Returns 0 for SUCCESS or -1 if FAILED. | ||
6859 | * | ||
6860 | * If -1 is return, then it was not possible to set the flags | ||
6861 | **/ | ||
6862 | int | ||
6863 | mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc) | ||
6864 | { | ||
6865 | unsigned long flags; | ||
6866 | int retval; | ||
6867 | |||
6868 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
6869 | if (ioc->ioc_reset_in_progress || ioc->taskmgmt_in_progress || | ||
6870 | (ioc->alt_ioc && ioc->alt_ioc->taskmgmt_in_progress)) { | ||
6871 | retval = -1; | ||
6872 | goto out; | ||
6873 | } | ||
6874 | retval = 0; | ||
6875 | ioc->taskmgmt_in_progress = 1; | ||
6876 | ioc->taskmgmt_quiesce_io = 1; | ||
6877 | if (ioc->alt_ioc) { | ||
6878 | ioc->alt_ioc->taskmgmt_in_progress = 1; | ||
6879 | ioc->alt_ioc->taskmgmt_quiesce_io = 1; | ||
6880 | } | ||
6881 | out: | ||
6882 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
6883 | return retval; | ||
6884 | } | ||
6885 | EXPORT_SYMBOL(mpt_set_taskmgmt_in_progress_flag); | ||
6886 | |||
6887 | /** | ||
6888 | * mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task managment | ||
6889 | * @ioc: Pointer to MPT_ADAPTER structure | ||
6890 | * | ||
6891 | **/ | ||
6892 | void | ||
6893 | mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc) | ||
6894 | { | ||
6895 | unsigned long flags; | ||
6896 | |||
6897 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
6898 | ioc->taskmgmt_in_progress = 0; | ||
6899 | ioc->taskmgmt_quiesce_io = 0; | ||
6900 | if (ioc->alt_ioc) { | ||
6901 | ioc->alt_ioc->taskmgmt_in_progress = 0; | ||
6902 | ioc->alt_ioc->taskmgmt_quiesce_io = 0; | ||
6903 | } | ||
6904 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
6905 | } | ||
6906 | EXPORT_SYMBOL(mpt_clear_taskmgmt_in_progress_flag); | ||
6347 | 6907 | ||
6348 | 6908 | ||
6349 | /** | 6909 | /** |
@@ -6397,7 +6957,9 @@ int | |||
6397 | mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) | 6957 | mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) |
6398 | { | 6958 | { |
6399 | int rc; | 6959 | int rc; |
6960 | u8 cb_idx; | ||
6400 | unsigned long flags; | 6961 | unsigned long flags; |
6962 | unsigned long time_count; | ||
6401 | 6963 | ||
6402 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name)); | 6964 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name)); |
6403 | #ifdef MFCNT | 6965 | #ifdef MFCNT |
@@ -6410,14 +6972,15 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) | |||
6410 | /* Reset the adapter. Prevent more than 1 call to | 6972 | /* Reset the adapter. Prevent more than 1 call to |
6411 | * mpt_do_ioc_recovery at any instant in time. | 6973 | * mpt_do_ioc_recovery at any instant in time. |
6412 | */ | 6974 | */ |
6413 | spin_lock_irqsave(&ioc->diagLock, flags); | 6975 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
6414 | if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){ | 6976 | if (ioc->ioc_reset_in_progress) { |
6415 | spin_unlock_irqrestore(&ioc->diagLock, flags); | 6977 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); |
6416 | return 0; | 6978 | return 0; |
6417 | } else { | ||
6418 | ioc->diagPending = 1; | ||
6419 | } | 6979 | } |
6420 | spin_unlock_irqrestore(&ioc->diagLock, flags); | 6980 | ioc->ioc_reset_in_progress = 1; |
6981 | if (ioc->alt_ioc) | ||
6982 | ioc->alt_ioc->ioc_reset_in_progress = 1; | ||
6983 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
6421 | 6984 | ||
6422 | /* FIXME: If do_ioc_recovery fails, repeat.... | 6985 | /* FIXME: If do_ioc_recovery fails, repeat.... |
6423 | */ | 6986 | */ |
@@ -6427,47 +6990,57 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) | |||
6427 | * Prevents timeouts occurring during a diagnostic reset...very bad. | 6990 | * Prevents timeouts occurring during a diagnostic reset...very bad. |
6428 | * For all other protocol drivers, this is a no-op. | 6991 | * For all other protocol drivers, this is a no-op. |
6429 | */ | 6992 | */ |
6430 | { | 6993 | for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { |
6431 | u8 cb_idx; | 6994 | if (MptResetHandlers[cb_idx]) { |
6432 | int r = 0; | 6995 | mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET); |
6433 | 6996 | if (ioc->alt_ioc) | |
6434 | for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { | 6997 | mpt_signal_reset(cb_idx, ioc->alt_ioc, |
6435 | if (MptResetHandlers[cb_idx]) { | 6998 | 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 | } | 6999 | } |
6446 | } | 7000 | } |
6447 | 7001 | ||
6448 | if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) { | 7002 | time_count = jiffies; |
6449 | printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc); | 7003 | rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag); |
7004 | if (rc != 0) { | ||
7005 | printk(KERN_WARNING MYNAM | ||
7006 | ": WARNING - (%d) Cannot recover %s\n", rc, ioc->name); | ||
7007 | } else { | ||
7008 | if (ioc->hard_resets < -1) | ||
7009 | ioc->hard_resets++; | ||
6450 | } | 7010 | } |
6451 | ioc->reload_fw = 0; | ||
6452 | if (ioc->alt_ioc) | ||
6453 | ioc->alt_ioc->reload_fw = 0; | ||
6454 | 7011 | ||
6455 | spin_lock_irqsave(&ioc->diagLock, flags); | 7012 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
6456 | ioc->diagPending = 0; | 7013 | ioc->ioc_reset_in_progress = 0; |
6457 | if (ioc->alt_ioc) | 7014 | ioc->taskmgmt_quiesce_io = 0; |
6458 | ioc->alt_ioc->diagPending = 0; | 7015 | ioc->taskmgmt_in_progress = 0; |
6459 | spin_unlock_irqrestore(&ioc->diagLock, flags); | 7016 | if (ioc->alt_ioc) { |
7017 | ioc->alt_ioc->ioc_reset_in_progress = 0; | ||
7018 | ioc->alt_ioc->taskmgmt_quiesce_io = 0; | ||
7019 | ioc->alt_ioc->taskmgmt_in_progress = 0; | ||
7020 | } | ||
7021 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
6460 | 7022 | ||
6461 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler rc = %d!\n", ioc->name, rc)); | 7023 | dtmprintk(ioc, |
7024 | printk(MYIOC_s_DEBUG_FMT | ||
7025 | "HardResetHandler: completed (%d seconds): %s\n", ioc->name, | ||
7026 | jiffies_to_msecs(jiffies - time_count)/1000, ((rc == 0) ? | ||
7027 | "SUCCESS" : "FAILED"))); | ||
6462 | 7028 | ||
6463 | return rc; | 7029 | return rc; |
6464 | } | 7030 | } |
6465 | 7031 | ||
6466 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 7032 | #ifdef CONFIG_FUSION_LOGGING |
6467 | static void | 7033 | static void |
6468 | EventDescriptionStr(u8 event, u32 evData0, char *evStr) | 7034 | mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply) |
6469 | { | 7035 | { |
6470 | char *ds = NULL; | 7036 | char *ds = NULL; |
7037 | u32 evData0; | ||
7038 | int ii; | ||
7039 | u8 event; | ||
7040 | char *evStr = ioc->evStr; | ||
7041 | |||
7042 | event = le32_to_cpu(pEventReply->Event) & 0xFF; | ||
7043 | evData0 = le32_to_cpu(pEventReply->Data[0]); | ||
6471 | 7044 | ||
6472 | switch(event) { | 7045 | switch(event) { |
6473 | case MPI_EVENT_NONE: | 7046 | case MPI_EVENT_NONE: |
@@ -6501,9 +7074,9 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
6501 | if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP) | 7074 | if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP) |
6502 | ds = "Loop State(LIP) Change"; | 7075 | ds = "Loop State(LIP) Change"; |
6503 | else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE) | 7076 | else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE) |
6504 | ds = "Loop State(LPE) Change"; /* ??? */ | 7077 | ds = "Loop State(LPE) Change"; |
6505 | else | 7078 | else |
6506 | ds = "Loop State(LPB) Change"; /* ??? */ | 7079 | ds = "Loop State(LPB) Change"; |
6507 | break; | 7080 | break; |
6508 | case MPI_EVENT_LOGOUT: | 7081 | case MPI_EVENT_LOGOUT: |
6509 | ds = "Logout"; | 7082 | ds = "Logout"; |
@@ -6703,28 +7276,65 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
6703 | } | 7276 | } |
6704 | case MPI_EVENT_IR2: | 7277 | case MPI_EVENT_IR2: |
6705 | { | 7278 | { |
7279 | u8 id = (u8)(evData0); | ||
7280 | u8 channel = (u8)(evData0 >> 8); | ||
7281 | u8 phys_num = (u8)(evData0 >> 24); | ||
6706 | u8 ReasonCode = (u8)(evData0 >> 16); | 7282 | u8 ReasonCode = (u8)(evData0 >> 16); |
7283 | |||
6707 | switch (ReasonCode) { | 7284 | switch (ReasonCode) { |
6708 | case MPI_EVENT_IR2_RC_LD_STATE_CHANGED: | 7285 | case MPI_EVENT_IR2_RC_LD_STATE_CHANGED: |
6709 | ds = "IR2: LD State Changed"; | 7286 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
7287 | "IR2: LD State Changed: " | ||
7288 | "id=%d channel=%d phys_num=%d", | ||
7289 | id, channel, phys_num); | ||
6710 | break; | 7290 | break; |
6711 | case MPI_EVENT_IR2_RC_PD_STATE_CHANGED: | 7291 | case MPI_EVENT_IR2_RC_PD_STATE_CHANGED: |
6712 | ds = "IR2: PD State Changed"; | 7292 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
7293 | "IR2: PD State Changed " | ||
7294 | "id=%d channel=%d phys_num=%d", | ||
7295 | id, channel, phys_num); | ||
6713 | break; | 7296 | break; |
6714 | case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL: | 7297 | case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL: |
6715 | ds = "IR2: Bad Block Table Full"; | 7298 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
7299 | "IR2: Bad Block Table Full: " | ||
7300 | "id=%d channel=%d phys_num=%d", | ||
7301 | id, channel, phys_num); | ||
6716 | break; | 7302 | break; |
6717 | case MPI_EVENT_IR2_RC_PD_INSERTED: | 7303 | case MPI_EVENT_IR2_RC_PD_INSERTED: |
6718 | ds = "IR2: PD Inserted"; | 7304 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
7305 | "IR2: PD Inserted: " | ||
7306 | "id=%d channel=%d phys_num=%d", | ||
7307 | id, channel, phys_num); | ||
6719 | break; | 7308 | break; |
6720 | case MPI_EVENT_IR2_RC_PD_REMOVED: | 7309 | case MPI_EVENT_IR2_RC_PD_REMOVED: |
6721 | ds = "IR2: PD Removed"; | 7310 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
7311 | "IR2: PD Removed: " | ||
7312 | "id=%d channel=%d phys_num=%d", | ||
7313 | id, channel, phys_num); | ||
6722 | break; | 7314 | break; |
6723 | case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: | 7315 | case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: |
6724 | ds = "IR2: Foreign CFG Detected"; | 7316 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
7317 | "IR2: Foreign CFG Detected: " | ||
7318 | "id=%d channel=%d phys_num=%d", | ||
7319 | id, channel, phys_num); | ||
6725 | break; | 7320 | break; |
6726 | case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR: | 7321 | case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR: |
6727 | ds = "IR2: Rebuild Medium Error"; | 7322 | snprintf(evStr, EVENT_DESCR_STR_SZ, |
7323 | "IR2: Rebuild Medium Error: " | ||
7324 | "id=%d channel=%d phys_num=%d", | ||
7325 | id, channel, phys_num); | ||
7326 | break; | ||
7327 | case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED: | ||
7328 | snprintf(evStr, EVENT_DESCR_STR_SZ, | ||
7329 | "IR2: Dual Port Added: " | ||
7330 | "id=%d channel=%d phys_num=%d", | ||
7331 | id, channel, phys_num); | ||
7332 | break; | ||
7333 | case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED: | ||
7334 | snprintf(evStr, EVENT_DESCR_STR_SZ, | ||
7335 | "IR2: Dual Port Removed: " | ||
7336 | "id=%d channel=%d phys_num=%d", | ||
7337 | id, channel, phys_num); | ||
6728 | break; | 7338 | break; |
6729 | default: | 7339 | default: |
6730 | ds = "IR2"; | 7340 | ds = "IR2"; |
@@ -6760,13 +7370,18 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
6760 | case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: | 7370 | case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: |
6761 | { | 7371 | { |
6762 | u8 reason = (u8)(evData0); | 7372 | u8 reason = (u8)(evData0); |
6763 | u8 port_num = (u8)(evData0 >> 8); | ||
6764 | u16 handle = le16_to_cpu(evData0 >> 16); | ||
6765 | 7373 | ||
6766 | snprintf(evStr, EVENT_DESCR_STR_SZ, | 7374 | switch (reason) { |
6767 | "SAS Initiator Device Status Change: reason=0x%02x " | 7375 | case MPI_EVENT_SAS_INIT_RC_ADDED: |
6768 | "port=%d handle=0x%04x", | 7376 | ds = "SAS Initiator Status Change: Added"; |
6769 | reason, port_num, handle); | 7377 | break; |
7378 | case MPI_EVENT_SAS_INIT_RC_REMOVED: | ||
7379 | ds = "SAS Initiator Status Change: Deleted"; | ||
7380 | break; | ||
7381 | default: | ||
7382 | ds = "SAS Initiator Status Change"; | ||
7383 | break; | ||
7384 | } | ||
6770 | break; | 7385 | break; |
6771 | } | 7386 | } |
6772 | 7387 | ||
@@ -6814,6 +7429,24 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
6814 | break; | 7429 | break; |
6815 | } | 7430 | } |
6816 | 7431 | ||
7432 | case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE: | ||
7433 | { | ||
7434 | u8 reason = (u8)(evData0); | ||
7435 | |||
7436 | switch (reason) { | ||
7437 | case MPI_EVENT_SAS_EXP_RC_ADDED: | ||
7438 | ds = "Expander Status Change: Added"; | ||
7439 | break; | ||
7440 | case MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING: | ||
7441 | ds = "Expander Status Change: Deleted"; | ||
7442 | break; | ||
7443 | default: | ||
7444 | ds = "Expander Status Change"; | ||
7445 | break; | ||
7446 | } | ||
7447 | break; | ||
7448 | } | ||
7449 | |||
6817 | /* | 7450 | /* |
6818 | * MPT base "custom" events may be added here... | 7451 | * MPT base "custom" events may be added here... |
6819 | */ | 7452 | */ |
@@ -6823,8 +7456,20 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
6823 | } | 7456 | } |
6824 | if (ds) | 7457 | if (ds) |
6825 | strncpy(evStr, ds, EVENT_DESCR_STR_SZ); | 7458 | strncpy(evStr, ds, EVENT_DESCR_STR_SZ); |
6826 | } | ||
6827 | 7459 | ||
7460 | |||
7461 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
7462 | "MPT event:(%02Xh) : %s\n", | ||
7463 | ioc->name, event, evStr)); | ||
7464 | |||
7465 | devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM | ||
7466 | ": Event data:\n")); | ||
7467 | for (ii = 0; ii < le16_to_cpu(pEventReply->EventDataLength); ii++) | ||
7468 | devtverboseprintk(ioc, printk(" %08x", | ||
7469 | le32_to_cpu(pEventReply->Data[ii]))); | ||
7470 | devtverboseprintk(ioc, printk(KERN_DEBUG "\n")); | ||
7471 | } | ||
7472 | #endif | ||
6828 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 7473 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
6829 | /** | 7474 | /** |
6830 | * ProcessEventNotification - Route EventNotificationReply to all event handlers | 7475 | * ProcessEventNotification - Route EventNotificationReply to all event handlers |
@@ -6841,37 +7486,24 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply | |||
6841 | { | 7486 | { |
6842 | u16 evDataLen; | 7487 | u16 evDataLen; |
6843 | u32 evData0 = 0; | 7488 | u32 evData0 = 0; |
6844 | // u32 evCtx; | ||
6845 | int ii; | 7489 | int ii; |
6846 | u8 cb_idx; | 7490 | u8 cb_idx; |
6847 | int r = 0; | 7491 | int r = 0; |
6848 | int handlers = 0; | 7492 | int handlers = 0; |
6849 | char evStr[EVENT_DESCR_STR_SZ]; | ||
6850 | u8 event; | 7493 | u8 event; |
6851 | 7494 | ||
6852 | /* | 7495 | /* |
6853 | * Do platform normalization of values | 7496 | * Do platform normalization of values |
6854 | */ | 7497 | */ |
6855 | event = le32_to_cpu(pEventReply->Event) & 0xFF; | 7498 | event = le32_to_cpu(pEventReply->Event) & 0xFF; |
6856 | // evCtx = le32_to_cpu(pEventReply->EventContext); | ||
6857 | evDataLen = le16_to_cpu(pEventReply->EventDataLength); | 7499 | evDataLen = le16_to_cpu(pEventReply->EventDataLength); |
6858 | if (evDataLen) { | 7500 | if (evDataLen) { |
6859 | evData0 = le32_to_cpu(pEventReply->Data[0]); | 7501 | evData0 = le32_to_cpu(pEventReply->Data[0]); |
6860 | } | 7502 | } |
6861 | 7503 | ||
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 | 7504 | #ifdef CONFIG_FUSION_LOGGING |
6869 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 7505 | if (evDataLen) |
6870 | ": Event data:\n", ioc->name)); | 7506 | 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 | 7507 | #endif |
6876 | 7508 | ||
6877 | /* | 7509 | /* |
@@ -6926,8 +7558,9 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply | |||
6926 | */ | 7558 | */ |
6927 | for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { | 7559 | for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { |
6928 | if (MptEvHandlers[cb_idx]) { | 7560 | if (MptEvHandlers[cb_idx]) { |
6929 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n", | 7561 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
6930 | ioc->name, cb_idx)); | 7562 | "Routing Event to event handler #%d\n", |
7563 | ioc->name, cb_idx)); | ||
6931 | r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply); | 7564 | r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply); |
6932 | handlers++; | 7565 | handlers++; |
6933 | } | 7566 | } |
@@ -7011,8 +7644,6 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) | |||
7011 | switch (info) { | 7644 | switch (info) { |
7012 | case 0x00010000: | 7645 | case 0x00010000: |
7013 | desc = "bug! MID not found"; | 7646 | desc = "bug! MID not found"; |
7014 | if (ioc->reload_fw == 0) | ||
7015 | ioc->reload_fw++; | ||
7016 | break; | 7647 | break; |
7017 | 7648 | ||
7018 | case 0x00020000: | 7649 | case 0x00020000: |
@@ -7613,7 +8244,6 @@ EXPORT_SYMBOL(mpt_get_msg_frame); | |||
7613 | EXPORT_SYMBOL(mpt_put_msg_frame); | 8244 | EXPORT_SYMBOL(mpt_put_msg_frame); |
7614 | EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri); | 8245 | EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri); |
7615 | EXPORT_SYMBOL(mpt_free_msg_frame); | 8246 | EXPORT_SYMBOL(mpt_free_msg_frame); |
7616 | EXPORT_SYMBOL(mpt_add_sge); | ||
7617 | EXPORT_SYMBOL(mpt_send_handshake_request); | 8247 | EXPORT_SYMBOL(mpt_send_handshake_request); |
7618 | EXPORT_SYMBOL(mpt_verify_adapter); | 8248 | EXPORT_SYMBOL(mpt_verify_adapter); |
7619 | EXPORT_SYMBOL(mpt_GetIocState); | 8249 | EXPORT_SYMBOL(mpt_GetIocState); |
@@ -7650,7 +8280,7 @@ fusion_init(void) | |||
7650 | /* Register ourselves (mptbase) in order to facilitate | 8280 | /* Register ourselves (mptbase) in order to facilitate |
7651 | * EventNotification handling. | 8281 | * EventNotification handling. |
7652 | */ | 8282 | */ |
7653 | mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER); | 8283 | mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER); |
7654 | 8284 | ||
7655 | /* Register for hard reset handling callbacks. | 8285 | /* Register for hard reset handling callbacks. |
7656 | */ | 8286 | */ |
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 a9019f081b97..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; |
@@ -1277,8 +2135,8 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
1277 | /* do we need to support multiple segments? */ | 2135 | /* do we need to support multiple segments? */ |
1278 | if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { | 2136 | if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { |
1279 | printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n", | 2137 | printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n", |
1280 | ioc->name, __func__, req->bio->bi_vcnt, req->data_len, | 2138 | ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req), |
1281 | rsp->bio->bi_vcnt, rsp->data_len); | 2139 | rsp->bio->bi_vcnt, blk_rq_bytes(rsp)); |
1282 | return -EINVAL; | 2140 | return -EINVAL; |
1283 | } | 2141 | } |
1284 | 2142 | ||
@@ -1295,7 +2153,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
1295 | smpreq = (SmpPassthroughRequest_t *)mf; | 2153 | smpreq = (SmpPassthroughRequest_t *)mf; |
1296 | memset(smpreq, 0, sizeof(*smpreq)); | 2154 | memset(smpreq, 0, sizeof(*smpreq)); |
1297 | 2155 | ||
1298 | smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4); | 2156 | smpreq->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4); |
1299 | smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH; | 2157 | smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH; |
1300 | 2158 | ||
1301 | if (rphy) | 2159 | if (rphy) |
@@ -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 |= (req->data_len - 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 | req->data_len, 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 | |
1335 | flagsLength |= rsp->data_len + 4; | 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; | ||
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 | rsp->data_len, 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,30 +2215,32 @@ 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; |
1358 | memcpy(req->sense, smprep, sizeof(*smprep)); | 2222 | memcpy(req->sense, smprep, sizeof(*smprep)); |
1359 | req->sense_len = sizeof(*smprep); | 2223 | req->sense_len = sizeof(*smprep); |
1360 | req->data_len = 0; | 2224 | req->resid_len = 0; |
1361 | rsp->data_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 | } |
1367 | unmap: | 2232 | unmap: |
1368 | if (dma_addr_out) | 2233 | if (dma_addr_out) |
1369 | pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len, | 2234 | pci_unmap_single(ioc->pcidev, dma_addr_out, blk_rq_bytes(req), |
1370 | PCI_DMA_BIDIRECTIONAL); | 2235 | PCI_DMA_BIDIRECTIONAL); |
1371 | if (dma_addr_in) | 2236 | if (dma_addr_in) |
1372 | pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len, | 2237 | pci_unmap_single(ioc->pcidev, dma_addr_in, blk_rq_bytes(rsp), |
1373 | PCI_DMA_BIDIRECTIONAL); | 2238 | PCI_DMA_BIDIRECTIONAL); |
1374 | put_mf: | 2239 | 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..8440f78f6969 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 | * @req: Pointer to original MPT request frame | ||
2679 | * @reply: Pointer to MPT reply frame (NULL if TurboReply) | ||
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 | ||