diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_base.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 603 |
1 files changed, 443 insertions, 160 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index d95d2f274cb3..89d02401b9ec 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * for access to MPT (Message Passing Technology) firmware. | 3 | * for access to MPT (Message Passing Technology) firmware. |
4 | * | 4 | * |
5 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.c | 5 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.c |
6 | * Copyright (C) 2007-2008 LSI Corporation | 6 | * Copyright (C) 2007-2009 LSI Corporation |
7 | * (mailto:DL-MPTFusionLinux@lsi.com) | 7 | * (mailto:DL-MPTFusionLinux@lsi.com) |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
@@ -57,13 +57,14 @@ | |||
57 | #include <linux/dma-mapping.h> | 57 | #include <linux/dma-mapping.h> |
58 | #include <linux/sort.h> | 58 | #include <linux/sort.h> |
59 | #include <linux/io.h> | 59 | #include <linux/io.h> |
60 | #include <linux/time.h> | ||
60 | 61 | ||
61 | #include "mpt2sas_base.h" | 62 | #include "mpt2sas_base.h" |
62 | 63 | ||
63 | static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; | 64 | static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; |
64 | 65 | ||
65 | #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ | 66 | #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ |
66 | #define MPT2SAS_MAX_REQUEST_QUEUE 500 /* maximum controller queue depth */ | 67 | #define MPT2SAS_MAX_REQUEST_QUEUE 600 /* maximum controller queue depth */ |
67 | 68 | ||
68 | static int max_queue_depth = -1; | 69 | static int max_queue_depth = -1; |
69 | module_param(max_queue_depth, int, 0); | 70 | module_param(max_queue_depth, int, 0); |
@@ -77,6 +78,44 @@ static int msix_disable = -1; | |||
77 | module_param(msix_disable, int, 0); | 78 | module_param(msix_disable, int, 0); |
78 | MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); | 79 | MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); |
79 | 80 | ||
81 | /* diag_buffer_enable is bitwise | ||
82 | * bit 0 set = TRACE | ||
83 | * bit 1 set = SNAPSHOT | ||
84 | * bit 2 set = EXTENDED | ||
85 | * | ||
86 | * Either bit can be set, or both | ||
87 | */ | ||
88 | static int diag_buffer_enable; | ||
89 | module_param(diag_buffer_enable, int, 0); | ||
90 | MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers " | ||
91 | "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)"); | ||
92 | |||
93 | int mpt2sas_fwfault_debug; | ||
94 | MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault " | ||
95 | "and halt firmware - (default=0)"); | ||
96 | |||
97 | /** | ||
98 | * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. | ||
99 | * | ||
100 | */ | ||
101 | static int | ||
102 | _scsih_set_fwfault_debug(const char *val, struct kernel_param *kp) | ||
103 | { | ||
104 | int ret = param_set_int(val, kp); | ||
105 | struct MPT2SAS_ADAPTER *ioc; | ||
106 | |||
107 | if (ret) | ||
108 | return ret; | ||
109 | |||
110 | printk(KERN_INFO "setting logging_level(0x%08x)\n", | ||
111 | mpt2sas_fwfault_debug); | ||
112 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) | ||
113 | ioc->fwfault_debug = mpt2sas_fwfault_debug; | ||
114 | return 0; | ||
115 | } | ||
116 | module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug, | ||
117 | param_get_int, &mpt2sas_fwfault_debug, 0644); | ||
118 | |||
80 | /** | 119 | /** |
81 | * _base_fault_reset_work - workq handling ioc fault conditions | 120 | * _base_fault_reset_work - workq handling ioc fault conditions |
82 | * @work: input argument, used to derive ioc | 121 | * @work: input argument, used to derive ioc |
@@ -121,7 +160,7 @@ _base_fault_reset_work(struct work_struct *work) | |||
121 | 160 | ||
122 | /** | 161 | /** |
123 | * mpt2sas_base_start_watchdog - start the fault_reset_work_q | 162 | * mpt2sas_base_start_watchdog - start the fault_reset_work_q |
124 | * @ioc: pointer to scsi command object | 163 | * @ioc: per adapter object |
125 | * Context: sleep. | 164 | * Context: sleep. |
126 | * | 165 | * |
127 | * Return nothing. | 166 | * Return nothing. |
@@ -155,7 +194,7 @@ mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc) | |||
155 | 194 | ||
156 | /** | 195 | /** |
157 | * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q | 196 | * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q |
158 | * @ioc: pointer to scsi command object | 197 | * @ioc: per adapter object |
159 | * Context: sleep. | 198 | * Context: sleep. |
160 | * | 199 | * |
161 | * Return nothing. | 200 | * Return nothing. |
@@ -177,10 +216,55 @@ mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc) | |||
177 | } | 216 | } |
178 | } | 217 | } |
179 | 218 | ||
219 | /** | ||
220 | * mpt2sas_base_fault_info - verbose translation of firmware FAULT code | ||
221 | * @ioc: per adapter object | ||
222 | * @fault_code: fault code | ||
223 | * | ||
224 | * Return nothing. | ||
225 | */ | ||
226 | void | ||
227 | mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code) | ||
228 | { | ||
229 | printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n", | ||
230 | ioc->name, fault_code); | ||
231 | } | ||
232 | |||
233 | /** | ||
234 | * mpt2sas_halt_firmware - halt's mpt controller firmware | ||
235 | * @ioc: per adapter object | ||
236 | * | ||
237 | * For debugging timeout related issues. Writing 0xCOFFEE00 | ||
238 | * to the doorbell register will halt controller firmware. With | ||
239 | * the purpose to stop both driver and firmware, the enduser can | ||
240 | * obtain a ring buffer from controller UART. | ||
241 | */ | ||
242 | void | ||
243 | mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc) | ||
244 | { | ||
245 | u32 doorbell; | ||
246 | |||
247 | if (!ioc->fwfault_debug) | ||
248 | return; | ||
249 | |||
250 | dump_stack(); | ||
251 | |||
252 | doorbell = readl(&ioc->chip->Doorbell); | ||
253 | if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) | ||
254 | mpt2sas_base_fault_info(ioc , doorbell); | ||
255 | else { | ||
256 | writel(0xC0FFEE00, &ioc->chip->Doorbell); | ||
257 | printk(MPT2SAS_ERR_FMT "Firmware is halted due to command " | ||
258 | "timeout\n", ioc->name); | ||
259 | } | ||
260 | |||
261 | panic("panic in %s\n", __func__); | ||
262 | } | ||
263 | |||
180 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 264 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
181 | /** | 265 | /** |
182 | * _base_sas_ioc_info - verbose translation of the ioc status | 266 | * _base_sas_ioc_info - verbose translation of the ioc status |
183 | * @ioc: pointer to scsi command object | 267 | * @ioc: per adapter object |
184 | * @mpi_reply: reply mf payload returned from firmware | 268 | * @mpi_reply: reply mf payload returned from firmware |
185 | * @request_hdr: request mf | 269 | * @request_hdr: request mf |
186 | * | 270 | * |
@@ -394,7 +478,7 @@ _base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply, | |||
394 | 478 | ||
395 | /** | 479 | /** |
396 | * _base_display_event_data - verbose translation of firmware asyn events | 480 | * _base_display_event_data - verbose translation of firmware asyn events |
397 | * @ioc: pointer to scsi command object | 481 | * @ioc: per adapter object |
398 | * @mpi_reply: reply mf payload returned from firmware | 482 | * @mpi_reply: reply mf payload returned from firmware |
399 | * | 483 | * |
400 | * Return nothing. | 484 | * Return nothing. |
@@ -474,7 +558,7 @@ _base_display_event_data(struct MPT2SAS_ADAPTER *ioc, | |||
474 | 558 | ||
475 | /** | 559 | /** |
476 | * _base_sas_log_info - verbose translation of firmware log info | 560 | * _base_sas_log_info - verbose translation of firmware log info |
477 | * @ioc: pointer to scsi command object | 561 | * @ioc: per adapter object |
478 | * @log_info: log info | 562 | * @log_info: log info |
479 | * | 563 | * |
480 | * Return nothing. | 564 | * Return nothing. |
@@ -526,30 +610,16 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info) | |||
526 | } | 610 | } |
527 | 611 | ||
528 | /** | 612 | /** |
529 | * mpt2sas_base_fault_info - verbose translation of firmware FAULT code | ||
530 | * @ioc: pointer to scsi command object | ||
531 | * @fault_code: fault code | ||
532 | * | ||
533 | * Return nothing. | ||
534 | */ | ||
535 | void | ||
536 | mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code) | ||
537 | { | ||
538 | printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n", | ||
539 | ioc->name, fault_code); | ||
540 | } | ||
541 | |||
542 | /** | ||
543 | * _base_display_reply_info - | 613 | * _base_display_reply_info - |
544 | * @ioc: pointer to scsi command object | 614 | * @ioc: per adapter object |
545 | * @smid: system request message index | 615 | * @smid: system request message index |
546 | * @VF_ID: virtual function id | 616 | * @msix_index: MSIX table index supplied by the OS |
547 | * @reply: reply message frame(lower 32bit addr) | 617 | * @reply: reply message frame(lower 32bit addr) |
548 | * | 618 | * |
549 | * Return nothing. | 619 | * Return nothing. |
550 | */ | 620 | */ |
551 | static void | 621 | static void |
552 | _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, | 622 | _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
553 | u32 reply) | 623 | u32 reply) |
554 | { | 624 | { |
555 | MPI2DefaultReply_t *mpi_reply; | 625 | MPI2DefaultReply_t *mpi_reply; |
@@ -570,24 +640,26 @@ _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, | |||
570 | 640 | ||
571 | /** | 641 | /** |
572 | * mpt2sas_base_done - base internal command completion routine | 642 | * mpt2sas_base_done - base internal command completion routine |
573 | * @ioc: pointer to scsi command object | 643 | * @ioc: per adapter object |
574 | * @smid: system request message index | 644 | * @smid: system request message index |
575 | * @VF_ID: virtual function id | 645 | * @msix_index: MSIX table index supplied by the OS |
576 | * @reply: reply message frame(lower 32bit addr) | 646 | * @reply: reply message frame(lower 32bit addr) |
577 | * | 647 | * |
578 | * Return nothing. | 648 | * Return 1 meaning mf should be freed from _base_interrupt |
649 | * 0 means the mf is freed from this function. | ||
579 | */ | 650 | */ |
580 | void | 651 | u8 |
581 | mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | 652 | mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
653 | u32 reply) | ||
582 | { | 654 | { |
583 | MPI2DefaultReply_t *mpi_reply; | 655 | MPI2DefaultReply_t *mpi_reply; |
584 | 656 | ||
585 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 657 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
586 | if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) | 658 | if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) |
587 | return; | 659 | return 1; |
588 | 660 | ||
589 | if (ioc->base_cmds.status == MPT2_CMD_NOT_USED) | 661 | if (ioc->base_cmds.status == MPT2_CMD_NOT_USED) |
590 | return; | 662 | return 1; |
591 | 663 | ||
592 | ioc->base_cmds.status |= MPT2_CMD_COMPLETE; | 664 | ioc->base_cmds.status |= MPT2_CMD_COMPLETE; |
593 | if (mpi_reply) { | 665 | if (mpi_reply) { |
@@ -596,18 +668,20 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | |||
596 | } | 668 | } |
597 | ioc->base_cmds.status &= ~MPT2_CMD_PENDING; | 669 | ioc->base_cmds.status &= ~MPT2_CMD_PENDING; |
598 | complete(&ioc->base_cmds.done); | 670 | complete(&ioc->base_cmds.done); |
671 | return 1; | ||
599 | } | 672 | } |
600 | 673 | ||
601 | /** | 674 | /** |
602 | * _base_async_event - main callback handler for firmware asyn events | 675 | * _base_async_event - main callback handler for firmware asyn events |
603 | * @ioc: pointer to scsi command object | 676 | * @ioc: per adapter object |
604 | * @VF_ID: virtual function id | 677 | * @msix_index: MSIX table index supplied by the OS |
605 | * @reply: reply message frame(lower 32bit addr) | 678 | * @reply: reply message frame(lower 32bit addr) |
606 | * | 679 | * |
607 | * Return nothing. | 680 | * Return 1 meaning mf should be freed from _base_interrupt |
681 | * 0 means the mf is freed from this function. | ||
608 | */ | 682 | */ |
609 | static void | 683 | static u8 |
610 | _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | 684 | _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply) |
611 | { | 685 | { |
612 | Mpi2EventNotificationReply_t *mpi_reply; | 686 | Mpi2EventNotificationReply_t *mpi_reply; |
613 | Mpi2EventAckRequest_t *ack_request; | 687 | Mpi2EventAckRequest_t *ack_request; |
@@ -615,9 +689,9 @@ _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | |||
615 | 689 | ||
616 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 690 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
617 | if (!mpi_reply) | 691 | if (!mpi_reply) |
618 | return; | 692 | return 1; |
619 | if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) | 693 | if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) |
620 | return; | 694 | return 1; |
621 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 695 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
622 | _base_display_event_data(ioc, mpi_reply); | 696 | _base_display_event_data(ioc, mpi_reply); |
623 | #endif | 697 | #endif |
@@ -635,21 +709,52 @@ _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | |||
635 | ack_request->Function = MPI2_FUNCTION_EVENT_ACK; | 709 | ack_request->Function = MPI2_FUNCTION_EVENT_ACK; |
636 | ack_request->Event = mpi_reply->Event; | 710 | ack_request->Event = mpi_reply->Event; |
637 | ack_request->EventContext = mpi_reply->EventContext; | 711 | ack_request->EventContext = mpi_reply->EventContext; |
638 | ack_request->VF_ID = VF_ID; | 712 | ack_request->VF_ID = 0; /* TODO */ |
639 | mpt2sas_base_put_smid_default(ioc, smid, VF_ID); | 713 | ack_request->VP_ID = 0; |
714 | mpt2sas_base_put_smid_default(ioc, smid); | ||
640 | 715 | ||
641 | out: | 716 | out: |
642 | 717 | ||
643 | /* scsih callback handler */ | 718 | /* scsih callback handler */ |
644 | mpt2sas_scsih_event_callback(ioc, VF_ID, reply); | 719 | mpt2sas_scsih_event_callback(ioc, msix_index, reply); |
645 | 720 | ||
646 | /* ctl callback handler */ | 721 | /* ctl callback handler */ |
647 | mpt2sas_ctl_event_callback(ioc, VF_ID, reply); | 722 | mpt2sas_ctl_event_callback(ioc, msix_index, reply); |
723 | |||
724 | return 1; | ||
725 | } | ||
726 | |||
727 | /** | ||
728 | * _base_get_cb_idx - obtain the callback index | ||
729 | * @ioc: per adapter object | ||
730 | * @smid: system request message index | ||
731 | * | ||
732 | * Return callback index. | ||
733 | */ | ||
734 | static u8 | ||
735 | _base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
736 | { | ||
737 | int i; | ||
738 | u8 cb_idx = 0xFF; | ||
739 | |||
740 | if (smid >= ioc->hi_priority_smid) { | ||
741 | if (smid < ioc->internal_smid) { | ||
742 | i = smid - ioc->hi_priority_smid; | ||
743 | cb_idx = ioc->hpr_lookup[i].cb_idx; | ||
744 | } else { | ||
745 | i = smid - ioc->internal_smid; | ||
746 | cb_idx = ioc->internal_lookup[i].cb_idx; | ||
747 | } | ||
748 | } else { | ||
749 | i = smid - 1; | ||
750 | cb_idx = ioc->scsi_lookup[i].cb_idx; | ||
751 | } | ||
752 | return cb_idx; | ||
648 | } | 753 | } |
649 | 754 | ||
650 | /** | 755 | /** |
651 | * _base_mask_interrupts - disable interrupts | 756 | * _base_mask_interrupts - disable interrupts |
652 | * @ioc: pointer to scsi command object | 757 | * @ioc: per adapter object |
653 | * | 758 | * |
654 | * Disabling ResetIRQ, Reply and Doorbell Interrupts | 759 | * Disabling ResetIRQ, Reply and Doorbell Interrupts |
655 | * | 760 | * |
@@ -669,7 +774,7 @@ _base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc) | |||
669 | 774 | ||
670 | /** | 775 | /** |
671 | * _base_unmask_interrupts - enable interrupts | 776 | * _base_unmask_interrupts - enable interrupts |
672 | * @ioc: pointer to scsi command object | 777 | * @ioc: per adapter object |
673 | * | 778 | * |
674 | * Enabling only Reply Interrupts | 779 | * Enabling only Reply Interrupts |
675 | * | 780 | * |
@@ -680,7 +785,6 @@ _base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc) | |||
680 | { | 785 | { |
681 | u32 him_register; | 786 | u32 him_register; |
682 | 787 | ||
683 | writel(0, &ioc->chip->HostInterruptStatus); | ||
684 | him_register = readl(&ioc->chip->HostInterruptMask); | 788 | him_register = readl(&ioc->chip->HostInterruptMask); |
685 | him_register &= ~MPI2_HIM_RIM; | 789 | him_register &= ~MPI2_HIM_RIM; |
686 | writel(him_register, &ioc->chip->HostInterruptMask); | 790 | writel(him_register, &ioc->chip->HostInterruptMask); |
@@ -712,9 +816,10 @@ _base_interrupt(int irq, void *bus_id) | |||
712 | u16 smid; | 816 | u16 smid; |
713 | u8 cb_idx; | 817 | u8 cb_idx; |
714 | u32 reply; | 818 | u32 reply; |
715 | u8 VF_ID; | 819 | u8 msix_index; |
716 | struct MPT2SAS_ADAPTER *ioc = bus_id; | 820 | struct MPT2SAS_ADAPTER *ioc = bus_id; |
717 | Mpi2ReplyDescriptorsUnion_t *rpf; | 821 | Mpi2ReplyDescriptorsUnion_t *rpf; |
822 | u8 rc; | ||
718 | 823 | ||
719 | if (ioc->mask_interrupts) | 824 | if (ioc->mask_interrupts) |
720 | return IRQ_NONE; | 825 | return IRQ_NONE; |
@@ -733,7 +838,7 @@ _base_interrupt(int irq, void *bus_id) | |||
733 | reply = 0; | 838 | reply = 0; |
734 | cb_idx = 0xFF; | 839 | cb_idx = 0xFF; |
735 | smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1); | 840 | smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1); |
736 | VF_ID = rpf->Default.VF_ID; | 841 | msix_index = rpf->Default.MSIxIndex; |
737 | if (request_desript_type == | 842 | if (request_desript_type == |
738 | MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { | 843 | MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { |
739 | reply = le32_to_cpu | 844 | reply = le32_to_cpu |
@@ -745,16 +850,18 @@ _base_interrupt(int irq, void *bus_id) | |||
745 | MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS) | 850 | MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS) |
746 | goto next; | 851 | goto next; |
747 | if (smid) | 852 | if (smid) |
748 | cb_idx = ioc->scsi_lookup[smid - 1].cb_idx; | 853 | cb_idx = _base_get_cb_idx(ioc, smid); |
749 | if (smid && cb_idx != 0xFF) { | 854 | if (smid && cb_idx != 0xFF) { |
750 | mpt_callbacks[cb_idx](ioc, smid, VF_ID, reply); | 855 | rc = mpt_callbacks[cb_idx](ioc, smid, msix_index, |
856 | reply); | ||
751 | if (reply) | 857 | if (reply) |
752 | _base_display_reply_info(ioc, smid, VF_ID, | 858 | _base_display_reply_info(ioc, smid, msix_index, |
753 | reply); | 859 | reply); |
754 | mpt2sas_base_free_smid(ioc, smid); | 860 | if (rc) |
861 | mpt2sas_base_free_smid(ioc, smid); | ||
755 | } | 862 | } |
756 | if (!smid) | 863 | if (!smid) |
757 | _base_async_event(ioc, VF_ID, reply); | 864 | _base_async_event(ioc, msix_index, reply); |
758 | 865 | ||
759 | /* reply free queue handling */ | 866 | /* reply free queue handling */ |
760 | if (reply) { | 867 | if (reply) { |
@@ -1191,19 +1298,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1191 | } | 1298 | } |
1192 | 1299 | ||
1193 | /** | 1300 | /** |
1194 | * mpt2sas_base_get_msg_frame_dma - obtain request mf pointer phys addr | ||
1195 | * @ioc: per adapter object | ||
1196 | * @smid: system request message index(smid zero is invalid) | ||
1197 | * | ||
1198 | * Returns phys pointer to message frame. | ||
1199 | */ | ||
1200 | dma_addr_t | ||
1201 | mpt2sas_base_get_msg_frame_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
1202 | { | ||
1203 | return ioc->request_dma + (smid * ioc->request_sz); | ||
1204 | } | ||
1205 | |||
1206 | /** | ||
1207 | * mpt2sas_base_get_msg_frame - obtain request mf pointer | 1301 | * mpt2sas_base_get_msg_frame - obtain request mf pointer |
1208 | * @ioc: per adapter object | 1302 | * @ioc: per adapter object |
1209 | * @smid: system request message index(smid zero is invalid) | 1303 | * @smid: system request message index(smid zero is invalid) |
@@ -1234,12 +1328,13 @@ mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid) | |||
1234 | * @ioc: per adapter object | 1328 | * @ioc: per adapter object |
1235 | * @smid: system request message index | 1329 | * @smid: system request message index |
1236 | * | 1330 | * |
1237 | * Returns phys pointer to sense buffer. | 1331 | * Returns phys pointer to the low 32bit address of the sense buffer. |
1238 | */ | 1332 | */ |
1239 | dma_addr_t | 1333 | __le32 |
1240 | mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) | 1334 | mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) |
1241 | { | 1335 | { |
1242 | return ioc->sense_dma + ((smid - 1) * SCSI_SENSE_BUFFERSIZE); | 1336 | return cpu_to_le32(ioc->sense_dma + |
1337 | ((smid - 1) * SCSI_SENSE_BUFFERSIZE)); | ||
1243 | } | 1338 | } |
1244 | 1339 | ||
1245 | /** | 1340 | /** |
@@ -1258,7 +1353,7 @@ mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr) | |||
1258 | } | 1353 | } |
1259 | 1354 | ||
1260 | /** | 1355 | /** |
1261 | * mpt2sas_base_get_smid - obtain a free smid | 1356 | * mpt2sas_base_get_smid - obtain a free smid from internal queue |
1262 | * @ioc: per adapter object | 1357 | * @ioc: per adapter object |
1263 | * @cb_idx: callback index | 1358 | * @cb_idx: callback index |
1264 | * | 1359 | * |
@@ -1272,6 +1367,39 @@ mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx) | |||
1272 | u16 smid; | 1367 | u16 smid; |
1273 | 1368 | ||
1274 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 1369 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
1370 | if (list_empty(&ioc->internal_free_list)) { | ||
1371 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
1372 | printk(MPT2SAS_ERR_FMT "%s: smid not available\n", | ||
1373 | ioc->name, __func__); | ||
1374 | return 0; | ||
1375 | } | ||
1376 | |||
1377 | request = list_entry(ioc->internal_free_list.next, | ||
1378 | struct request_tracker, tracker_list); | ||
1379 | request->cb_idx = cb_idx; | ||
1380 | smid = request->smid; | ||
1381 | list_del(&request->tracker_list); | ||
1382 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
1383 | return smid; | ||
1384 | } | ||
1385 | |||
1386 | /** | ||
1387 | * mpt2sas_base_get_smid_scsiio - obtain a free smid from scsiio queue | ||
1388 | * @ioc: per adapter object | ||
1389 | * @cb_idx: callback index | ||
1390 | * @scmd: pointer to scsi command object | ||
1391 | * | ||
1392 | * Returns smid (zero is invalid) | ||
1393 | */ | ||
1394 | u16 | ||
1395 | mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx, | ||
1396 | struct scsi_cmnd *scmd) | ||
1397 | { | ||
1398 | unsigned long flags; | ||
1399 | struct request_tracker *request; | ||
1400 | u16 smid; | ||
1401 | |||
1402 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
1275 | if (list_empty(&ioc->free_list)) { | 1403 | if (list_empty(&ioc->free_list)) { |
1276 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 1404 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
1277 | printk(MPT2SAS_ERR_FMT "%s: smid not available\n", | 1405 | printk(MPT2SAS_ERR_FMT "%s: smid not available\n", |
@@ -1281,6 +1409,36 @@ mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx) | |||
1281 | 1409 | ||
1282 | request = list_entry(ioc->free_list.next, | 1410 | request = list_entry(ioc->free_list.next, |
1283 | struct request_tracker, tracker_list); | 1411 | struct request_tracker, tracker_list); |
1412 | request->scmd = scmd; | ||
1413 | request->cb_idx = cb_idx; | ||
1414 | smid = request->smid; | ||
1415 | list_del(&request->tracker_list); | ||
1416 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
1417 | return smid; | ||
1418 | } | ||
1419 | |||
1420 | /** | ||
1421 | * mpt2sas_base_get_smid_hpr - obtain a free smid from hi-priority queue | ||
1422 | * @ioc: per adapter object | ||
1423 | * @cb_idx: callback index | ||
1424 | * | ||
1425 | * Returns smid (zero is invalid) | ||
1426 | */ | ||
1427 | u16 | ||
1428 | mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx) | ||
1429 | { | ||
1430 | unsigned long flags; | ||
1431 | struct request_tracker *request; | ||
1432 | u16 smid; | ||
1433 | |||
1434 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
1435 | if (list_empty(&ioc->hpr_free_list)) { | ||
1436 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
1437 | return 0; | ||
1438 | } | ||
1439 | |||
1440 | request = list_entry(ioc->hpr_free_list.next, | ||
1441 | struct request_tracker, tracker_list); | ||
1284 | request->cb_idx = cb_idx; | 1442 | request->cb_idx = cb_idx; |
1285 | smid = request->smid; | 1443 | smid = request->smid; |
1286 | list_del(&request->tracker_list); | 1444 | list_del(&request->tracker_list); |
@@ -1300,10 +1458,32 @@ void | |||
1300 | mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) | 1458 | mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) |
1301 | { | 1459 | { |
1302 | unsigned long flags; | 1460 | unsigned long flags; |
1461 | int i; | ||
1303 | 1462 | ||
1304 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 1463 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
1305 | ioc->scsi_lookup[smid - 1].cb_idx = 0xFF; | 1464 | if (smid >= ioc->hi_priority_smid) { |
1306 | list_add_tail(&ioc->scsi_lookup[smid - 1].tracker_list, | 1465 | if (smid < ioc->internal_smid) { |
1466 | /* hi-priority */ | ||
1467 | i = smid - ioc->hi_priority_smid; | ||
1468 | ioc->hpr_lookup[i].cb_idx = 0xFF; | ||
1469 | list_add_tail(&ioc->hpr_lookup[i].tracker_list, | ||
1470 | &ioc->hpr_free_list); | ||
1471 | } else { | ||
1472 | /* internal queue */ | ||
1473 | i = smid - ioc->internal_smid; | ||
1474 | ioc->internal_lookup[i].cb_idx = 0xFF; | ||
1475 | list_add_tail(&ioc->internal_lookup[i].tracker_list, | ||
1476 | &ioc->internal_free_list); | ||
1477 | } | ||
1478 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
1479 | return; | ||
1480 | } | ||
1481 | |||
1482 | /* scsiio queue */ | ||
1483 | i = smid - 1; | ||
1484 | ioc->scsi_lookup[i].cb_idx = 0xFF; | ||
1485 | ioc->scsi_lookup[i].scmd = NULL; | ||
1486 | list_add_tail(&ioc->scsi_lookup[i].tracker_list, | ||
1307 | &ioc->free_list); | 1487 | &ioc->free_list); |
1308 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 1488 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
1309 | 1489 | ||
@@ -1352,21 +1532,19 @@ static inline void _base_writeq(__u64 b, volatile void __iomem *addr, | |||
1352 | * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware | 1532 | * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware |
1353 | * @ioc: per adapter object | 1533 | * @ioc: per adapter object |
1354 | * @smid: system request message index | 1534 | * @smid: system request message index |
1355 | * @vf_id: virtual function id | ||
1356 | * @handle: device handle | 1535 | * @handle: device handle |
1357 | * | 1536 | * |
1358 | * Return nothing. | 1537 | * Return nothing. |
1359 | */ | 1538 | */ |
1360 | void | 1539 | void |
1361 | mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id, | 1540 | mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle) |
1362 | u16 handle) | ||
1363 | { | 1541 | { |
1364 | Mpi2RequestDescriptorUnion_t descriptor; | 1542 | Mpi2RequestDescriptorUnion_t descriptor; |
1365 | u64 *request = (u64 *)&descriptor; | 1543 | u64 *request = (u64 *)&descriptor; |
1366 | 1544 | ||
1367 | 1545 | ||
1368 | descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; | 1546 | descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; |
1369 | descriptor.SCSIIO.VF_ID = vf_id; | 1547 | descriptor.SCSIIO.MSIxIndex = 0; /* TODO */ |
1370 | descriptor.SCSIIO.SMID = cpu_to_le16(smid); | 1548 | descriptor.SCSIIO.SMID = cpu_to_le16(smid); |
1371 | descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); | 1549 | descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); |
1372 | descriptor.SCSIIO.LMID = 0; | 1550 | descriptor.SCSIIO.LMID = 0; |
@@ -1379,20 +1557,18 @@ mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id, | |||
1379 | * mpt2sas_base_put_smid_hi_priority - send Task Managment request to firmware | 1557 | * mpt2sas_base_put_smid_hi_priority - send Task Managment request to firmware |
1380 | * @ioc: per adapter object | 1558 | * @ioc: per adapter object |
1381 | * @smid: system request message index | 1559 | * @smid: system request message index |
1382 | * @vf_id: virtual function id | ||
1383 | * | 1560 | * |
1384 | * Return nothing. | 1561 | * Return nothing. |
1385 | */ | 1562 | */ |
1386 | void | 1563 | void |
1387 | mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid, | 1564 | mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid) |
1388 | u8 vf_id) | ||
1389 | { | 1565 | { |
1390 | Mpi2RequestDescriptorUnion_t descriptor; | 1566 | Mpi2RequestDescriptorUnion_t descriptor; |
1391 | u64 *request = (u64 *)&descriptor; | 1567 | u64 *request = (u64 *)&descriptor; |
1392 | 1568 | ||
1393 | descriptor.HighPriority.RequestFlags = | 1569 | descriptor.HighPriority.RequestFlags = |
1394 | MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; | 1570 | MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; |
1395 | descriptor.HighPriority.VF_ID = vf_id; | 1571 | descriptor.HighPriority.MSIxIndex = 0; /* TODO */ |
1396 | descriptor.HighPriority.SMID = cpu_to_le16(smid); | 1572 | descriptor.HighPriority.SMID = cpu_to_le16(smid); |
1397 | descriptor.HighPriority.LMID = 0; | 1573 | descriptor.HighPriority.LMID = 0; |
1398 | descriptor.HighPriority.Reserved1 = 0; | 1574 | descriptor.HighPriority.Reserved1 = 0; |
@@ -1404,18 +1580,17 @@ mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |||
1404 | * mpt2sas_base_put_smid_default - Default, primarily used for config pages | 1580 | * mpt2sas_base_put_smid_default - Default, primarily used for config pages |
1405 | * @ioc: per adapter object | 1581 | * @ioc: per adapter object |
1406 | * @smid: system request message index | 1582 | * @smid: system request message index |
1407 | * @vf_id: virtual function id | ||
1408 | * | 1583 | * |
1409 | * Return nothing. | 1584 | * Return nothing. |
1410 | */ | 1585 | */ |
1411 | void | 1586 | void |
1412 | mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id) | 1587 | mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid) |
1413 | { | 1588 | { |
1414 | Mpi2RequestDescriptorUnion_t descriptor; | 1589 | Mpi2RequestDescriptorUnion_t descriptor; |
1415 | u64 *request = (u64 *)&descriptor; | 1590 | u64 *request = (u64 *)&descriptor; |
1416 | 1591 | ||
1417 | descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; | 1592 | descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; |
1418 | descriptor.Default.VF_ID = vf_id; | 1593 | descriptor.Default.MSIxIndex = 0; /* TODO */ |
1419 | descriptor.Default.SMID = cpu_to_le16(smid); | 1594 | descriptor.Default.SMID = cpu_to_le16(smid); |
1420 | descriptor.Default.LMID = 0; | 1595 | descriptor.Default.LMID = 0; |
1421 | descriptor.Default.DescriptorTypeDependent = 0; | 1596 | descriptor.Default.DescriptorTypeDependent = 0; |
@@ -1427,21 +1602,20 @@ mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id) | |||
1427 | * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware | 1602 | * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware |
1428 | * @ioc: per adapter object | 1603 | * @ioc: per adapter object |
1429 | * @smid: system request message index | 1604 | * @smid: system request message index |
1430 | * @vf_id: virtual function id | ||
1431 | * @io_index: value used to track the IO | 1605 | * @io_index: value used to track the IO |
1432 | * | 1606 | * |
1433 | * Return nothing. | 1607 | * Return nothing. |
1434 | */ | 1608 | */ |
1435 | void | 1609 | void |
1436 | mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, | 1610 | mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, |
1437 | u8 vf_id, u16 io_index) | 1611 | u16 io_index) |
1438 | { | 1612 | { |
1439 | Mpi2RequestDescriptorUnion_t descriptor; | 1613 | Mpi2RequestDescriptorUnion_t descriptor; |
1440 | u64 *request = (u64 *)&descriptor; | 1614 | u64 *request = (u64 *)&descriptor; |
1441 | 1615 | ||
1442 | descriptor.SCSITarget.RequestFlags = | 1616 | descriptor.SCSITarget.RequestFlags = |
1443 | MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET; | 1617 | MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET; |
1444 | descriptor.SCSITarget.VF_ID = vf_id; | 1618 | descriptor.SCSITarget.MSIxIndex = 0; /* TODO */ |
1445 | descriptor.SCSITarget.SMID = cpu_to_le16(smid); | 1619 | descriptor.SCSITarget.SMID = cpu_to_le16(smid); |
1446 | descriptor.SCSITarget.LMID = 0; | 1620 | descriptor.SCSITarget.LMID = 0; |
1447 | descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index); | 1621 | descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index); |
@@ -1594,6 +1768,12 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) | |||
1594 | } | 1768 | } |
1595 | 1769 | ||
1596 | if (ioc->facts.IOCCapabilities & | 1770 | if (ioc->facts.IOCCapabilities & |
1771 | MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) { | ||
1772 | printk(KERN_INFO "%sDiag Extended Buffer", i ? "," : ""); | ||
1773 | i++; | ||
1774 | } | ||
1775 | |||
1776 | if (ioc->facts.IOCCapabilities & | ||
1597 | MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) { | 1777 | MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) { |
1598 | printk("%sTask Set Full", i ? "," : ""); | 1778 | printk("%sTask Set Full", i ? "," : ""); |
1599 | i++; | 1779 | i++; |
@@ -1717,6 +1897,8 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) | |||
1717 | } | 1897 | } |
1718 | 1898 | ||
1719 | kfree(ioc->scsi_lookup); | 1899 | kfree(ioc->scsi_lookup); |
1900 | kfree(ioc->hpr_lookup); | ||
1901 | kfree(ioc->internal_lookup); | ||
1720 | } | 1902 | } |
1721 | 1903 | ||
1722 | 1904 | ||
@@ -1736,7 +1918,6 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1736 | u16 num_of_reply_frames; | 1918 | u16 num_of_reply_frames; |
1737 | u16 chains_needed_per_io; | 1919 | u16 chains_needed_per_io; |
1738 | u32 sz, total_sz; | 1920 | u32 sz, total_sz; |
1739 | u16 i; | ||
1740 | u32 retry_sz; | 1921 | u32 retry_sz; |
1741 | u16 max_request_credit; | 1922 | u16 max_request_credit; |
1742 | 1923 | ||
@@ -1764,7 +1945,10 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1764 | MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE : | 1945 | MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE : |
1765 | facts->RequestCredit; | 1946 | facts->RequestCredit; |
1766 | } | 1947 | } |
1767 | ioc->request_depth = max_request_credit; | 1948 | |
1949 | ioc->hba_queue_depth = max_request_credit; | ||
1950 | ioc->hi_priority_depth = facts->HighPriorityCredit; | ||
1951 | ioc->internal_depth = ioc->hi_priority_depth + 5; | ||
1768 | 1952 | ||
1769 | /* request frame size */ | 1953 | /* request frame size */ |
1770 | ioc->request_sz = facts->IOCRequestFrameSize * 4; | 1954 | ioc->request_sz = facts->IOCRequestFrameSize * 4; |
@@ -1802,7 +1986,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1802 | ioc->chains_needed_per_io = chains_needed_per_io; | 1986 | ioc->chains_needed_per_io = chains_needed_per_io; |
1803 | 1987 | ||
1804 | /* reply free queue sizing - taking into account for events */ | 1988 | /* reply free queue sizing - taking into account for events */ |
1805 | num_of_reply_frames = ioc->request_depth + 32; | 1989 | num_of_reply_frames = ioc->hba_queue_depth + 32; |
1806 | 1990 | ||
1807 | /* number of replies frames can't be a multiple of 16 */ | 1991 | /* number of replies frames can't be a multiple of 16 */ |
1808 | /* decrease number of reply frames by 1 */ | 1992 | /* decrease number of reply frames by 1 */ |
@@ -1823,7 +2007,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1823 | * frames | 2007 | * frames |
1824 | */ | 2008 | */ |
1825 | 2009 | ||
1826 | queue_size = ioc->request_depth + num_of_reply_frames + 1; | 2010 | queue_size = ioc->hba_queue_depth + num_of_reply_frames + 1; |
1827 | /* round up to 16 byte boundary */ | 2011 | /* round up to 16 byte boundary */ |
1828 | if (queue_size % 16) | 2012 | if (queue_size % 16) |
1829 | queue_size += 16 - (queue_size % 16); | 2013 | queue_size += 16 - (queue_size % 16); |
@@ -1837,60 +2021,85 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1837 | if (queue_diff % 16) | 2021 | if (queue_diff % 16) |
1838 | queue_diff += 16 - (queue_diff % 16); | 2022 | queue_diff += 16 - (queue_diff % 16); |
1839 | 2023 | ||
1840 | /* adjust request_depth, reply_free_queue_depth, | 2024 | /* adjust hba_queue_depth, reply_free_queue_depth, |
1841 | * and queue_size | 2025 | * and queue_size |
1842 | */ | 2026 | */ |
1843 | ioc->request_depth -= queue_diff; | 2027 | ioc->hba_queue_depth -= queue_diff; |
1844 | ioc->reply_free_queue_depth -= queue_diff; | 2028 | ioc->reply_free_queue_depth -= queue_diff; |
1845 | queue_size -= queue_diff; | 2029 | queue_size -= queue_diff; |
1846 | } | 2030 | } |
1847 | ioc->reply_post_queue_depth = queue_size; | 2031 | ioc->reply_post_queue_depth = queue_size; |
1848 | 2032 | ||
1849 | /* max scsi host queue depth */ | ||
1850 | ioc->shost->can_queue = ioc->request_depth - INTERNAL_CMDS_COUNT; | ||
1851 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host queue: depth" | ||
1852 | "(%d)\n", ioc->name, ioc->shost->can_queue)); | ||
1853 | |||
1854 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: " | 2033 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: " |
1855 | "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), " | 2034 | "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), " |
1856 | "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message, | 2035 | "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message, |
1857 | ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize, | 2036 | ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize, |
1858 | ioc->chains_needed_per_io)); | 2037 | ioc->chains_needed_per_io)); |
1859 | 2038 | ||
2039 | ioc->scsiio_depth = ioc->hba_queue_depth - | ||
2040 | ioc->hi_priority_depth - ioc->internal_depth; | ||
2041 | |||
2042 | /* set the scsi host can_queue depth | ||
2043 | * with some internal commands that could be outstanding | ||
2044 | */ | ||
2045 | ioc->shost->can_queue = ioc->scsiio_depth - (2); | ||
2046 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: " | ||
2047 | "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue)); | ||
2048 | |||
1860 | /* contiguous pool for request and chains, 16 byte align, one extra " | 2049 | /* contiguous pool for request and chains, 16 byte align, one extra " |
1861 | * "frame for smid=0 | 2050 | * "frame for smid=0 |
1862 | */ | 2051 | */ |
1863 | ioc->chain_depth = ioc->chains_needed_per_io * ioc->request_depth; | 2052 | ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth; |
1864 | sz = ((ioc->request_depth + 1 + ioc->chain_depth) * ioc->request_sz); | 2053 | sz = ((ioc->scsiio_depth + 1 + ioc->chain_depth) * ioc->request_sz); |
2054 | |||
2055 | /* hi-priority queue */ | ||
2056 | sz += (ioc->hi_priority_depth * ioc->request_sz); | ||
2057 | |||
2058 | /* internal queue */ | ||
2059 | sz += (ioc->internal_depth * ioc->request_sz); | ||
1865 | 2060 | ||
1866 | ioc->request_dma_sz = sz; | 2061 | ioc->request_dma_sz = sz; |
1867 | ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma); | 2062 | ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma); |
1868 | if (!ioc->request) { | 2063 | if (!ioc->request) { |
1869 | printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " | 2064 | printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " |
1870 | "failed: req_depth(%d), chains_per_io(%d), frame_sz(%d), " | 2065 | "failed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), " |
1871 | "total(%d kB)\n", ioc->name, ioc->request_depth, | 2066 | "total(%d kB)\n", ioc->name, ioc->hba_queue_depth, |
1872 | ioc->chains_needed_per_io, ioc->request_sz, sz/1024); | 2067 | ioc->chains_needed_per_io, ioc->request_sz, sz/1024); |
1873 | if (ioc->request_depth < MPT2SAS_SAS_QUEUE_DEPTH) | 2068 | if (ioc->scsiio_depth < MPT2SAS_SAS_QUEUE_DEPTH) |
1874 | goto out; | 2069 | goto out; |
1875 | retry_sz += 64; | 2070 | retry_sz += 64; |
1876 | ioc->request_depth = max_request_credit - retry_sz; | 2071 | ioc->hba_queue_depth = max_request_credit - retry_sz; |
1877 | goto retry_allocation; | 2072 | goto retry_allocation; |
1878 | } | 2073 | } |
1879 | 2074 | ||
1880 | if (retry_sz) | 2075 | if (retry_sz) |
1881 | printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " | 2076 | printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " |
1882 | "succeed: req_depth(%d), chains_per_io(%d), frame_sz(%d), " | 2077 | "succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), " |
1883 | "total(%d kb)\n", ioc->name, ioc->request_depth, | 2078 | "total(%d kb)\n", ioc->name, ioc->hba_queue_depth, |
1884 | ioc->chains_needed_per_io, ioc->request_sz, sz/1024); | 2079 | ioc->chains_needed_per_io, ioc->request_sz, sz/1024); |
1885 | 2080 | ||
1886 | ioc->chain = ioc->request + ((ioc->request_depth + 1) * | 2081 | |
2082 | /* hi-priority queue */ | ||
2083 | ioc->hi_priority = ioc->request + ((ioc->scsiio_depth + 1) * | ||
2084 | ioc->request_sz); | ||
2085 | ioc->hi_priority_dma = ioc->request_dma + ((ioc->scsiio_depth + 1) * | ||
2086 | ioc->request_sz); | ||
2087 | |||
2088 | /* internal queue */ | ||
2089 | ioc->internal = ioc->hi_priority + (ioc->hi_priority_depth * | ||
2090 | ioc->request_sz); | ||
2091 | ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth * | ||
2092 | ioc->request_sz); | ||
2093 | |||
2094 | ioc->chain = ioc->internal + (ioc->internal_depth * | ||
1887 | ioc->request_sz); | 2095 | ioc->request_sz); |
1888 | ioc->chain_dma = ioc->request_dma + ((ioc->request_depth + 1) * | 2096 | ioc->chain_dma = ioc->internal_dma + (ioc->internal_depth * |
1889 | ioc->request_sz); | 2097 | ioc->request_sz); |
2098 | |||
1890 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): " | 2099 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): " |
1891 | "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, | 2100 | "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, |
1892 | ioc->request, ioc->request_depth, ioc->request_sz, | 2101 | ioc->request, ioc->hba_queue_depth, ioc->request_sz, |
1893 | ((ioc->request_depth + 1) * ioc->request_sz)/1024)); | 2102 | (ioc->hba_queue_depth * ioc->request_sz)/1024)); |
1894 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth" | 2103 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth" |
1895 | "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain, | 2104 | "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain, |
1896 | ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth * | 2105 | ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth * |
@@ -1899,7 +2108,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1899 | ioc->name, (unsigned long long) ioc->request_dma)); | 2108 | ioc->name, (unsigned long long) ioc->request_dma)); |
1900 | total_sz += sz; | 2109 | total_sz += sz; |
1901 | 2110 | ||
1902 | ioc->scsi_lookup = kcalloc(ioc->request_depth, | 2111 | ioc->scsi_lookup = kcalloc(ioc->scsiio_depth, |
1903 | sizeof(struct request_tracker), GFP_KERNEL); | 2112 | sizeof(struct request_tracker), GFP_KERNEL); |
1904 | if (!ioc->scsi_lookup) { | 2113 | if (!ioc->scsi_lookup) { |
1905 | printk(MPT2SAS_ERR_FMT "scsi_lookup: kcalloc failed\n", | 2114 | printk(MPT2SAS_ERR_FMT "scsi_lookup: kcalloc failed\n", |
@@ -1907,12 +2116,38 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1907 | goto out; | 2116 | goto out; |
1908 | } | 2117 | } |
1909 | 2118 | ||
1910 | /* initialize some bits */ | 2119 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsiio(0x%p): " |
1911 | for (i = 0; i < ioc->request_depth; i++) | 2120 | "depth(%d)\n", ioc->name, ioc->request, |
1912 | ioc->scsi_lookup[i].smid = i + 1; | 2121 | ioc->scsiio_depth)); |
2122 | |||
2123 | /* initialize hi-priority queue smid's */ | ||
2124 | ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth, | ||
2125 | sizeof(struct request_tracker), GFP_KERNEL); | ||
2126 | if (!ioc->hpr_lookup) { | ||
2127 | printk(MPT2SAS_ERR_FMT "hpr_lookup: kcalloc failed\n", | ||
2128 | ioc->name); | ||
2129 | goto out; | ||
2130 | } | ||
2131 | ioc->hi_priority_smid = ioc->scsiio_depth + 1; | ||
2132 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hi_priority(0x%p): " | ||
2133 | "depth(%d), start smid(%d)\n", ioc->name, ioc->hi_priority, | ||
2134 | ioc->hi_priority_depth, ioc->hi_priority_smid)); | ||
2135 | |||
2136 | /* initialize internal queue smid's */ | ||
2137 | ioc->internal_lookup = kcalloc(ioc->internal_depth, | ||
2138 | sizeof(struct request_tracker), GFP_KERNEL); | ||
2139 | if (!ioc->internal_lookup) { | ||
2140 | printk(MPT2SAS_ERR_FMT "internal_lookup: kcalloc failed\n", | ||
2141 | ioc->name); | ||
2142 | goto out; | ||
2143 | } | ||
2144 | ioc->internal_smid = ioc->hi_priority_smid + ioc->hi_priority_depth; | ||
2145 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "internal(0x%p): " | ||
2146 | "depth(%d), start smid(%d)\n", ioc->name, ioc->internal, | ||
2147 | ioc->internal_depth, ioc->internal_smid)); | ||
1913 | 2148 | ||
1914 | /* sense buffers, 4 byte align */ | 2149 | /* sense buffers, 4 byte align */ |
1915 | sz = ioc->request_depth * SCSI_SENSE_BUFFERSIZE; | 2150 | sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE; |
1916 | ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4, | 2151 | ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4, |
1917 | 0); | 2152 | 0); |
1918 | if (!ioc->sense_dma_pool) { | 2153 | if (!ioc->sense_dma_pool) { |
@@ -1929,7 +2164,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1929 | } | 2164 | } |
1930 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT | 2165 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT |
1931 | "sense pool(0x%p): depth(%d), element_size(%d), pool_size" | 2166 | "sense pool(0x%p): depth(%d), element_size(%d), pool_size" |
1932 | "(%d kB)\n", ioc->name, ioc->sense, ioc->request_depth, | 2167 | "(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth, |
1933 | SCSI_SENSE_BUFFERSIZE, sz/1024)); | 2168 | SCSI_SENSE_BUFFERSIZE, sz/1024)); |
1934 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n", | 2169 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n", |
1935 | ioc->name, (unsigned long long)ioc->sense_dma)); | 2170 | ioc->name, (unsigned long long)ioc->sense_dma)); |
@@ -2304,7 +2539,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes, | |||
2304 | ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)), | 2539 | ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)), |
2305 | &ioc->chip->Doorbell); | 2540 | &ioc->chip->Doorbell); |
2306 | 2541 | ||
2307 | if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { | 2542 | if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) { |
2308 | printk(MPT2SAS_ERR_FMT "doorbell handshake " | 2543 | printk(MPT2SAS_ERR_FMT "doorbell handshake " |
2309 | "int failed (line=%d)\n", ioc->name, __LINE__); | 2544 | "int failed (line=%d)\n", ioc->name, __LINE__); |
2310 | return -EFAULT; | 2545 | return -EFAULT; |
@@ -2454,7 +2689,8 @@ mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc, | |||
2454 | if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || | 2689 | if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || |
2455 | mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) | 2690 | mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) |
2456 | ioc->ioc_link_reset_in_progress = 1; | 2691 | ioc->ioc_link_reset_in_progress = 1; |
2457 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 2692 | mpt2sas_base_put_smid_default(ioc, smid); |
2693 | init_completion(&ioc->base_cmds.done); | ||
2458 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, | 2694 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, |
2459 | msecs_to_jiffies(10000)); | 2695 | msecs_to_jiffies(10000)); |
2460 | if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || | 2696 | if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || |
@@ -2555,7 +2791,8 @@ mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc, | |||
2555 | request = mpt2sas_base_get_msg_frame(ioc, smid); | 2791 | request = mpt2sas_base_get_msg_frame(ioc, smid); |
2556 | ioc->base_cmds.smid = smid; | 2792 | ioc->base_cmds.smid = smid; |
2557 | memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); | 2793 | memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); |
2558 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 2794 | mpt2sas_base_put_smid_default(ioc, smid); |
2795 | init_completion(&ioc->base_cmds.done); | ||
2559 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, | 2796 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, |
2560 | msecs_to_jiffies(10000)); | 2797 | msecs_to_jiffies(10000)); |
2561 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { | 2798 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { |
@@ -2701,17 +2938,18 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
2701 | /** | 2938 | /** |
2702 | * _base_send_ioc_init - send ioc_init to firmware | 2939 | * _base_send_ioc_init - send ioc_init to firmware |
2703 | * @ioc: per adapter object | 2940 | * @ioc: per adapter object |
2704 | * @VF_ID: virtual function id | ||
2705 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | 2941 | * @sleep_flag: CAN_SLEEP or NO_SLEEP |
2706 | * | 2942 | * |
2707 | * Returns 0 for success, non-zero for failure. | 2943 | * Returns 0 for success, non-zero for failure. |
2708 | */ | 2944 | */ |
2709 | static int | 2945 | static int |
2710 | _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | 2946 | _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) |
2711 | { | 2947 | { |
2712 | Mpi2IOCInitRequest_t mpi_request; | 2948 | Mpi2IOCInitRequest_t mpi_request; |
2713 | Mpi2IOCInitReply_t mpi_reply; | 2949 | Mpi2IOCInitReply_t mpi_reply; |
2714 | int r; | 2950 | int r; |
2951 | struct timeval current_time; | ||
2952 | u16 ioc_status; | ||
2715 | 2953 | ||
2716 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 2954 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
2717 | __func__)); | 2955 | __func__)); |
@@ -2719,7 +2957,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | |||
2719 | memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t)); | 2957 | memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t)); |
2720 | mpi_request.Function = MPI2_FUNCTION_IOC_INIT; | 2958 | mpi_request.Function = MPI2_FUNCTION_IOC_INIT; |
2721 | mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; | 2959 | mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; |
2722 | mpi_request.VF_ID = VF_ID; | 2960 | mpi_request.VF_ID = 0; /* TODO */ |
2961 | mpi_request.VP_ID = 0; | ||
2723 | mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION); | 2962 | mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION); |
2724 | mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); | 2963 | mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); |
2725 | 2964 | ||
@@ -2761,6 +3000,13 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | |||
2761 | cpu_to_le32(ioc->reply_post_free_dma); | 3000 | cpu_to_le32(ioc->reply_post_free_dma); |
2762 | #endif | 3001 | #endif |
2763 | 3002 | ||
3003 | /* This time stamp specifies number of milliseconds | ||
3004 | * since epoch ~ midnight January 1, 1970. | ||
3005 | */ | ||
3006 | do_gettimeofday(¤t_time); | ||
3007 | mpi_request.TimeStamp = (current_time.tv_sec * 1000) + | ||
3008 | (current_time.tv_usec >> 3); | ||
3009 | |||
2764 | if (ioc->logging_level & MPT_DEBUG_INIT) { | 3010 | if (ioc->logging_level & MPT_DEBUG_INIT) { |
2765 | u32 *mfp; | 3011 | u32 *mfp; |
2766 | int i; | 3012 | int i; |
@@ -2783,7 +3029,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | |||
2783 | return r; | 3029 | return r; |
2784 | } | 3030 | } |
2785 | 3031 | ||
2786 | if (mpi_reply.IOCStatus != MPI2_IOCSTATUS_SUCCESS || | 3032 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; |
3033 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS || | ||
2787 | mpi_reply.IOCLogInfo) { | 3034 | mpi_reply.IOCLogInfo) { |
2788 | printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__); | 3035 | printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__); |
2789 | r = -EIO; | 3036 | r = -EIO; |
@@ -2795,13 +3042,12 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | |||
2795 | /** | 3042 | /** |
2796 | * _base_send_port_enable - send port_enable(discovery stuff) to firmware | 3043 | * _base_send_port_enable - send port_enable(discovery stuff) to firmware |
2797 | * @ioc: per adapter object | 3044 | * @ioc: per adapter object |
2798 | * @VF_ID: virtual function id | ||
2799 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | 3045 | * @sleep_flag: CAN_SLEEP or NO_SLEEP |
2800 | * | 3046 | * |
2801 | * Returns 0 for success, non-zero for failure. | 3047 | * Returns 0 for success, non-zero for failure. |
2802 | */ | 3048 | */ |
2803 | static int | 3049 | static int |
2804 | _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | 3050 | _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) |
2805 | { | 3051 | { |
2806 | Mpi2PortEnableRequest_t *mpi_request; | 3052 | Mpi2PortEnableRequest_t *mpi_request; |
2807 | u32 ioc_state; | 3053 | u32 ioc_state; |
@@ -2829,9 +3075,11 @@ _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | |||
2829 | ioc->base_cmds.smid = smid; | 3075 | ioc->base_cmds.smid = smid; |
2830 | memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); | 3076 | memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); |
2831 | mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; | 3077 | mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; |
2832 | mpi_request->VF_ID = VF_ID; | 3078 | mpi_request->VF_ID = 0; /* TODO */ |
3079 | mpi_request->VP_ID = 0; | ||
2833 | 3080 | ||
2834 | mpt2sas_base_put_smid_default(ioc, smid, VF_ID); | 3081 | mpt2sas_base_put_smid_default(ioc, smid); |
3082 | init_completion(&ioc->base_cmds.done); | ||
2835 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, | 3083 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, |
2836 | 300*HZ); | 3084 | 300*HZ); |
2837 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { | 3085 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { |
@@ -2892,13 +3140,12 @@ _base_unmask_events(struct MPT2SAS_ADAPTER *ioc, u16 event) | |||
2892 | /** | 3140 | /** |
2893 | * _base_event_notification - send event notification | 3141 | * _base_event_notification - send event notification |
2894 | * @ioc: per adapter object | 3142 | * @ioc: per adapter object |
2895 | * @VF_ID: virtual function id | ||
2896 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | 3143 | * @sleep_flag: CAN_SLEEP or NO_SLEEP |
2897 | * | 3144 | * |
2898 | * Returns 0 for success, non-zero for failure. | 3145 | * Returns 0 for success, non-zero for failure. |
2899 | */ | 3146 | */ |
2900 | static int | 3147 | static int |
2901 | _base_event_notification(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | 3148 | _base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) |
2902 | { | 3149 | { |
2903 | Mpi2EventNotificationRequest_t *mpi_request; | 3150 | Mpi2EventNotificationRequest_t *mpi_request; |
2904 | unsigned long timeleft; | 3151 | unsigned long timeleft; |
@@ -2926,11 +3173,13 @@ _base_event_notification(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | |||
2926 | ioc->base_cmds.smid = smid; | 3173 | ioc->base_cmds.smid = smid; |
2927 | memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t)); | 3174 | memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t)); |
2928 | mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; | 3175 | mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; |
2929 | mpi_request->VF_ID = VF_ID; | 3176 | mpi_request->VF_ID = 0; /* TODO */ |
3177 | mpi_request->VP_ID = 0; | ||
2930 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) | 3178 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) |
2931 | mpi_request->EventMasks[i] = | 3179 | mpi_request->EventMasks[i] = |
2932 | le32_to_cpu(ioc->event_masks[i]); | 3180 | le32_to_cpu(ioc->event_masks[i]); |
2933 | mpt2sas_base_put_smid_default(ioc, smid, VF_ID); | 3181 | mpt2sas_base_put_smid_default(ioc, smid); |
3182 | init_completion(&ioc->base_cmds.done); | ||
2934 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); | 3183 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); |
2935 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { | 3184 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { |
2936 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | 3185 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", |
@@ -2981,7 +3230,7 @@ mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type) | |||
2981 | return; | 3230 | return; |
2982 | 3231 | ||
2983 | mutex_lock(&ioc->base_cmds.mutex); | 3232 | mutex_lock(&ioc->base_cmds.mutex); |
2984 | _base_event_notification(ioc, 0, CAN_SLEEP); | 3233 | _base_event_notification(ioc, CAN_SLEEP); |
2985 | mutex_unlock(&ioc->base_cmds.mutex); | 3234 | mutex_unlock(&ioc->base_cmds.mutex); |
2986 | } | 3235 | } |
2987 | 3236 | ||
@@ -3006,7 +3255,6 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3006 | 3255 | ||
3007 | drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "clear interrupts\n", | 3256 | drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "clear interrupts\n", |
3008 | ioc->name)); | 3257 | ioc->name)); |
3009 | writel(0, &ioc->chip->HostInterruptStatus); | ||
3010 | 3258 | ||
3011 | count = 0; | 3259 | count = 0; |
3012 | do { | 3260 | do { |
@@ -3160,30 +3408,60 @@ _base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
3160 | /** | 3408 | /** |
3161 | * _base_make_ioc_operational - put controller in OPERATIONAL state | 3409 | * _base_make_ioc_operational - put controller in OPERATIONAL state |
3162 | * @ioc: per adapter object | 3410 | * @ioc: per adapter object |
3163 | * @VF_ID: virtual function id | ||
3164 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | 3411 | * @sleep_flag: CAN_SLEEP or NO_SLEEP |
3165 | * | 3412 | * |
3166 | * Returns 0 for success, non-zero for failure. | 3413 | * Returns 0 for success, non-zero for failure. |
3167 | */ | 3414 | */ |
3168 | static int | 3415 | static int |
3169 | _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | 3416 | _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) |
3170 | int sleep_flag) | ||
3171 | { | 3417 | { |
3172 | int r, i; | 3418 | int r, i; |
3173 | unsigned long flags; | 3419 | unsigned long flags; |
3174 | u32 reply_address; | 3420 | u32 reply_address; |
3421 | u16 smid; | ||
3422 | struct _tr_list *delayed_tr, *delayed_tr_next; | ||
3175 | 3423 | ||
3176 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 3424 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
3177 | __func__)); | 3425 | __func__)); |
3178 | 3426 | ||
3427 | /* clean the delayed target reset list */ | ||
3428 | list_for_each_entry_safe(delayed_tr, delayed_tr_next, | ||
3429 | &ioc->delayed_tr_list, list) { | ||
3430 | list_del(&delayed_tr->list); | ||
3431 | kfree(delayed_tr); | ||
3432 | } | ||
3433 | |||
3179 | /* initialize the scsi lookup free list */ | 3434 | /* initialize the scsi lookup free list */ |
3180 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 3435 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
3181 | INIT_LIST_HEAD(&ioc->free_list); | 3436 | INIT_LIST_HEAD(&ioc->free_list); |
3182 | for (i = 0; i < ioc->request_depth; i++) { | 3437 | smid = 1; |
3438 | for (i = 0; i < ioc->scsiio_depth; i++, smid++) { | ||
3183 | ioc->scsi_lookup[i].cb_idx = 0xFF; | 3439 | ioc->scsi_lookup[i].cb_idx = 0xFF; |
3440 | ioc->scsi_lookup[i].smid = smid; | ||
3441 | ioc->scsi_lookup[i].scmd = NULL; | ||
3184 | list_add_tail(&ioc->scsi_lookup[i].tracker_list, | 3442 | list_add_tail(&ioc->scsi_lookup[i].tracker_list, |
3185 | &ioc->free_list); | 3443 | &ioc->free_list); |
3186 | } | 3444 | } |
3445 | |||
3446 | /* hi-priority queue */ | ||
3447 | INIT_LIST_HEAD(&ioc->hpr_free_list); | ||
3448 | smid = ioc->hi_priority_smid; | ||
3449 | for (i = 0; i < ioc->hi_priority_depth; i++, smid++) { | ||
3450 | ioc->hpr_lookup[i].cb_idx = 0xFF; | ||
3451 | ioc->hpr_lookup[i].smid = smid; | ||
3452 | list_add_tail(&ioc->hpr_lookup[i].tracker_list, | ||
3453 | &ioc->hpr_free_list); | ||
3454 | } | ||
3455 | |||
3456 | /* internal queue */ | ||
3457 | INIT_LIST_HEAD(&ioc->internal_free_list); | ||
3458 | smid = ioc->internal_smid; | ||
3459 | for (i = 0; i < ioc->internal_depth; i++, smid++) { | ||
3460 | ioc->internal_lookup[i].cb_idx = 0xFF; | ||
3461 | ioc->internal_lookup[i].smid = smid; | ||
3462 | list_add_tail(&ioc->internal_lookup[i].tracker_list, | ||
3463 | &ioc->internal_free_list); | ||
3464 | } | ||
3187 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 3465 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
3188 | 3466 | ||
3189 | /* initialize Reply Free Queue */ | 3467 | /* initialize Reply Free Queue */ |
@@ -3196,7 +3474,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
3196 | for (i = 0; i < ioc->reply_post_queue_depth; i++) | 3474 | for (i = 0; i < ioc->reply_post_queue_depth; i++) |
3197 | ioc->reply_post_free[i].Words = ULLONG_MAX; | 3475 | ioc->reply_post_free[i].Words = ULLONG_MAX; |
3198 | 3476 | ||
3199 | r = _base_send_ioc_init(ioc, VF_ID, sleep_flag); | 3477 | r = _base_send_ioc_init(ioc, sleep_flag); |
3200 | if (r) | 3478 | if (r) |
3201 | return r; | 3479 | return r; |
3202 | 3480 | ||
@@ -3207,14 +3485,14 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
3207 | writel(0, &ioc->chip->ReplyPostHostIndex); | 3485 | writel(0, &ioc->chip->ReplyPostHostIndex); |
3208 | 3486 | ||
3209 | _base_unmask_interrupts(ioc); | 3487 | _base_unmask_interrupts(ioc); |
3210 | r = _base_event_notification(ioc, VF_ID, sleep_flag); | 3488 | r = _base_event_notification(ioc, sleep_flag); |
3211 | if (r) | 3489 | if (r) |
3212 | return r; | 3490 | return r; |
3213 | 3491 | ||
3214 | if (sleep_flag == CAN_SLEEP) | 3492 | if (sleep_flag == CAN_SLEEP) |
3215 | _base_static_config_pages(ioc); | 3493 | _base_static_config_pages(ioc); |
3216 | 3494 | ||
3217 | r = _base_send_port_enable(ioc, VF_ID, sleep_flag); | 3495 | r = _base_send_port_enable(ioc, sleep_flag); |
3218 | if (r) | 3496 | if (r) |
3219 | return r; | 3497 | return r; |
3220 | 3498 | ||
@@ -3270,14 +3548,25 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3270 | return r; | 3548 | return r; |
3271 | 3549 | ||
3272 | pci_set_drvdata(ioc->pdev, ioc->shost); | 3550 | pci_set_drvdata(ioc->pdev, ioc->shost); |
3273 | r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | 3551 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); |
3274 | if (r) | 3552 | if (r) |
3275 | goto out_free_resources; | 3553 | goto out_free_resources; |
3276 | 3554 | ||
3277 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); | 3555 | r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); |
3278 | if (r) | 3556 | if (r) |
3279 | goto out_free_resources; | 3557 | goto out_free_resources; |
3280 | 3558 | ||
3559 | ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts, | ||
3560 | sizeof(Mpi2PortFactsReply_t), GFP_KERNEL); | ||
3561 | if (!ioc->pfacts) | ||
3562 | goto out_free_resources; | ||
3563 | |||
3564 | for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { | ||
3565 | r = _base_get_port_facts(ioc, i, CAN_SLEEP); | ||
3566 | if (r) | ||
3567 | goto out_free_resources; | ||
3568 | } | ||
3569 | |||
3281 | r = _base_allocate_memory_pools(ioc, CAN_SLEEP); | 3570 | r = _base_allocate_memory_pools(ioc, CAN_SLEEP); |
3282 | if (r) | 3571 | if (r) |
3283 | goto out_free_resources; | 3572 | goto out_free_resources; |
@@ -3286,7 +3575,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3286 | 3575 | ||
3287 | /* base internal command bits */ | 3576 | /* base internal command bits */ |
3288 | mutex_init(&ioc->base_cmds.mutex); | 3577 | mutex_init(&ioc->base_cmds.mutex); |
3289 | init_completion(&ioc->base_cmds.done); | ||
3290 | ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 3578 | ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
3291 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | 3579 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; |
3292 | 3580 | ||
@@ -3294,7 +3582,11 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3294 | ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 3582 | ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
3295 | ioc->transport_cmds.status = MPT2_CMD_NOT_USED; | 3583 | ioc->transport_cmds.status = MPT2_CMD_NOT_USED; |
3296 | mutex_init(&ioc->transport_cmds.mutex); | 3584 | mutex_init(&ioc->transport_cmds.mutex); |
3297 | init_completion(&ioc->transport_cmds.done); | 3585 | |
3586 | /* scsih internal command bits */ | ||
3587 | ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | ||
3588 | ioc->scsih_cmds.status = MPT2_CMD_NOT_USED; | ||
3589 | mutex_init(&ioc->scsih_cmds.mutex); | ||
3298 | 3590 | ||
3299 | /* task management internal command bits */ | 3591 | /* task management internal command bits */ |
3300 | ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 3592 | ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
@@ -3310,7 +3602,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3310 | ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 3602 | ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
3311 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | 3603 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; |
3312 | mutex_init(&ioc->ctl_cmds.mutex); | 3604 | mutex_init(&ioc->ctl_cmds.mutex); |
3313 | init_completion(&ioc->ctl_cmds.done); | ||
3314 | 3605 | ||
3315 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) | 3606 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) |
3316 | ioc->event_masks[i] = -1; | 3607 | ioc->event_masks[i] = -1; |
@@ -3327,22 +3618,13 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3327 | _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS); | 3618 | _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS); |
3328 | _base_unmask_events(ioc, MPI2_EVENT_TASK_SET_FULL); | 3619 | _base_unmask_events(ioc, MPI2_EVENT_TASK_SET_FULL); |
3329 | _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); | 3620 | _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); |
3330 | 3621 | r = _base_make_ioc_operational(ioc, CAN_SLEEP); | |
3331 | ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts, | ||
3332 | sizeof(Mpi2PortFactsReply_t), GFP_KERNEL); | ||
3333 | if (!ioc->pfacts) | ||
3334 | goto out_free_resources; | ||
3335 | |||
3336 | for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { | ||
3337 | r = _base_get_port_facts(ioc, i, CAN_SLEEP); | ||
3338 | if (r) | ||
3339 | goto out_free_resources; | ||
3340 | } | ||
3341 | r = _base_make_ioc_operational(ioc, 0, CAN_SLEEP); | ||
3342 | if (r) | 3622 | if (r) |
3343 | goto out_free_resources; | 3623 | goto out_free_resources; |
3344 | 3624 | ||
3345 | mpt2sas_base_start_watchdog(ioc); | 3625 | mpt2sas_base_start_watchdog(ioc); |
3626 | if (diag_buffer_enable != 0) | ||
3627 | mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable); | ||
3346 | return 0; | 3628 | return 0; |
3347 | 3629 | ||
3348 | out_free_resources: | 3630 | out_free_resources: |
@@ -3466,7 +3748,7 @@ _wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3466 | 3748 | ||
3467 | /* pending command count */ | 3749 | /* pending command count */ |
3468 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 3750 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
3469 | for (i = 0; i < ioc->request_depth; i++) | 3751 | for (i = 0; i < ioc->scsiio_depth; i++) |
3470 | if (ioc->scsi_lookup[i].cb_idx != 0xFF) | 3752 | if (ioc->scsi_lookup[i].cb_idx != 0xFF) |
3471 | ioc->pending_io_count++; | 3753 | ioc->pending_io_count++; |
3472 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 3754 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
@@ -3490,12 +3772,15 @@ int | |||
3490 | mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | 3772 | mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, |
3491 | enum reset_type type) | 3773 | enum reset_type type) |
3492 | { | 3774 | { |
3493 | int r, i; | 3775 | int r; |
3494 | unsigned long flags; | 3776 | unsigned long flags; |
3495 | 3777 | ||
3496 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, | 3778 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, |
3497 | __func__)); | 3779 | __func__)); |
3498 | 3780 | ||
3781 | if (mpt2sas_fwfault_debug) | ||
3782 | mpt2sas_halt_firmware(ioc); | ||
3783 | |||
3499 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 3784 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); |
3500 | if (ioc->shost_recovery) { | 3785 | if (ioc->shost_recovery) { |
3501 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | 3786 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); |
@@ -3513,9 +3798,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
3513 | if (r) | 3798 | if (r) |
3514 | goto out; | 3799 | goto out; |
3515 | _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET); | 3800 | _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET); |
3516 | for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) | 3801 | r = _base_make_ioc_operational(ioc, sleep_flag); |
3517 | r = _base_make_ioc_operational(ioc, ioc->pfacts[i].VF_ID, | ||
3518 | sleep_flag); | ||
3519 | if (!r) | 3802 | if (!r) |
3520 | _base_reset_handler(ioc, MPT2_IOC_DONE_RESET); | 3803 | _base_reset_handler(ioc, MPT2_IOC_DONE_RESET); |
3521 | out: | 3804 | out: |