diff options
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas.c')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 366 |
1 files changed, 278 insertions, 88 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 4cab5b534b25..977b6e8d8525 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | * | 11 | * |
12 | * FILE : megaraid_sas.c | 12 | * FILE : megaraid_sas.c |
13 | * Version : v00.00.03.01 | 13 | * Version : v00.00.03.05 |
14 | * | 14 | * |
15 | * Authors: | 15 | * Authors: |
16 | * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com> | 16 | * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com> |
@@ -71,6 +71,8 @@ static struct megasas_mgmt_info megasas_mgmt_info; | |||
71 | static struct fasync_struct *megasas_async_queue; | 71 | static struct fasync_struct *megasas_async_queue; |
72 | static DEFINE_MUTEX(megasas_async_queue_mutex); | 72 | static DEFINE_MUTEX(megasas_async_queue_mutex); |
73 | 73 | ||
74 | static u32 megasas_dbg_lvl; | ||
75 | |||
74 | /** | 76 | /** |
75 | * megasas_get_cmd - Get a command from the free pool | 77 | * megasas_get_cmd - Get a command from the free pool |
76 | * @instance: Adapter soft state | 78 | * @instance: Adapter soft state |
@@ -135,6 +137,19 @@ megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs) | |||
135 | } | 137 | } |
136 | 138 | ||
137 | /** | 139 | /** |
140 | * megasas_disable_intr_xscale -Disables interrupt | ||
141 | * @regs: MFI register set | ||
142 | */ | ||
143 | static inline void | ||
144 | megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs) | ||
145 | { | ||
146 | u32 mask = 0x1f; | ||
147 | writel(mask, ®s->outbound_intr_mask); | ||
148 | /* Dummy readl to force pci flush */ | ||
149 | readl(®s->outbound_intr_mask); | ||
150 | } | ||
151 | |||
152 | /** | ||
138 | * megasas_read_fw_status_reg_xscale - returns the current FW status value | 153 | * megasas_read_fw_status_reg_xscale - returns the current FW status value |
139 | * @regs: MFI register set | 154 | * @regs: MFI register set |
140 | */ | 155 | */ |
@@ -185,6 +200,7 @@ static struct megasas_instance_template megasas_instance_template_xscale = { | |||
185 | 200 | ||
186 | .fire_cmd = megasas_fire_cmd_xscale, | 201 | .fire_cmd = megasas_fire_cmd_xscale, |
187 | .enable_intr = megasas_enable_intr_xscale, | 202 | .enable_intr = megasas_enable_intr_xscale, |
203 | .disable_intr = megasas_disable_intr_xscale, | ||
188 | .clear_intr = megasas_clear_intr_xscale, | 204 | .clear_intr = megasas_clear_intr_xscale, |
189 | .read_fw_status_reg = megasas_read_fw_status_reg_xscale, | 205 | .read_fw_status_reg = megasas_read_fw_status_reg_xscale, |
190 | }; | 206 | }; |
@@ -215,6 +231,19 @@ megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs) | |||
215 | } | 231 | } |
216 | 232 | ||
217 | /** | 233 | /** |
234 | * megasas_disable_intr_ppc - Disable interrupt | ||
235 | * @regs: MFI register set | ||
236 | */ | ||
237 | static inline void | ||
238 | megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs) | ||
239 | { | ||
240 | u32 mask = 0xFFFFFFFF; | ||
241 | writel(mask, ®s->outbound_intr_mask); | ||
242 | /* Dummy readl to force pci flush */ | ||
243 | readl(®s->outbound_intr_mask); | ||
244 | } | ||
245 | |||
246 | /** | ||
218 | * megasas_read_fw_status_reg_ppc - returns the current FW status value | 247 | * megasas_read_fw_status_reg_ppc - returns the current FW status value |
219 | * @regs: MFI register set | 248 | * @regs: MFI register set |
220 | */ | 249 | */ |
@@ -265,6 +294,7 @@ static struct megasas_instance_template megasas_instance_template_ppc = { | |||
265 | 294 | ||
266 | .fire_cmd = megasas_fire_cmd_ppc, | 295 | .fire_cmd = megasas_fire_cmd_ppc, |
267 | .enable_intr = megasas_enable_intr_ppc, | 296 | .enable_intr = megasas_enable_intr_ppc, |
297 | .disable_intr = megasas_disable_intr_ppc, | ||
268 | .clear_intr = megasas_clear_intr_ppc, | 298 | .clear_intr = megasas_clear_intr_ppc, |
269 | .read_fw_status_reg = megasas_read_fw_status_reg_ppc, | 299 | .read_fw_status_reg = megasas_read_fw_status_reg_ppc, |
270 | }; | 300 | }; |
@@ -275,25 +305,6 @@ static struct megasas_instance_template megasas_instance_template_ppc = { | |||
275 | */ | 305 | */ |
276 | 306 | ||
277 | /** | 307 | /** |
278 | * megasas_disable_intr - Disables interrupts | ||
279 | * @regs: MFI register set | ||
280 | */ | ||
281 | static inline void | ||
282 | megasas_disable_intr(struct megasas_instance *instance) | ||
283 | { | ||
284 | u32 mask = 0x1f; | ||
285 | struct megasas_register_set __iomem *regs = instance->reg_set; | ||
286 | |||
287 | if(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078R) | ||
288 | mask = 0xffffffff; | ||
289 | |||
290 | writel(mask, ®s->outbound_intr_mask); | ||
291 | |||
292 | /* Dummy readl to force pci flush */ | ||
293 | readl(®s->outbound_intr_mask); | ||
294 | } | ||
295 | |||
296 | /** | ||
297 | * megasas_issue_polled - Issues a polling command | 308 | * megasas_issue_polled - Issues a polling command |
298 | * @instance: Adapter soft state | 309 | * @instance: Adapter soft state |
299 | * @cmd: Command packet to be issued | 310 | * @cmd: Command packet to be issued |
@@ -336,6 +347,7 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) | |||
336 | * @cmd: Command to be issued | 347 | * @cmd: Command to be issued |
337 | * | 348 | * |
338 | * This function waits on an event for the command to be returned from ISR. | 349 | * This function waits on an event for the command to be returned from ISR. |
350 | * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs | ||
339 | * Used to issue ioctl commands. | 351 | * Used to issue ioctl commands. |
340 | */ | 352 | */ |
341 | static int | 353 | static int |
@@ -346,7 +358,8 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, | |||
346 | 358 | ||
347 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); | 359 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); |
348 | 360 | ||
349 | wait_event(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA)); | 361 | wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA), |
362 | MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ); | ||
350 | 363 | ||
351 | return 0; | 364 | return 0; |
352 | } | 365 | } |
@@ -358,7 +371,8 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, | |||
358 | * | 371 | * |
359 | * MFI firmware can abort previously issued AEN comamnd (automatic event | 372 | * MFI firmware can abort previously issued AEN comamnd (automatic event |
360 | * notification). The megasas_issue_blocked_abort_cmd() issues such abort | 373 | * notification). The megasas_issue_blocked_abort_cmd() issues such abort |
361 | * cmd and blocks till it is completed. | 374 | * cmd and waits for return status. |
375 | * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs | ||
362 | */ | 376 | */ |
363 | static int | 377 | static int |
364 | megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, | 378 | megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, |
@@ -392,7 +406,8 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, | |||
392 | /* | 406 | /* |
393 | * Wait for this cmd to complete | 407 | * Wait for this cmd to complete |
394 | */ | 408 | */ |
395 | wait_event(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF)); | 409 | wait_event_timeout(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF), |
410 | MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ); | ||
396 | 411 | ||
397 | megasas_return_cmd(instance, cmd); | 412 | megasas_return_cmd(instance, cmd); |
398 | return 0; | 413 | return 0; |
@@ -495,6 +510,46 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
495 | return sge_count; | 510 | return sge_count; |
496 | } | 511 | } |
497 | 512 | ||
513 | /** | ||
514 | * megasas_get_frame_count - Computes the number of frames | ||
515 | * @sge_count : number of sg elements | ||
516 | * | ||
517 | * Returns the number of frames required for numnber of sge's (sge_count) | ||
518 | */ | ||
519 | |||
520 | u32 megasas_get_frame_count(u8 sge_count) | ||
521 | { | ||
522 | int num_cnt; | ||
523 | int sge_bytes; | ||
524 | u32 sge_sz; | ||
525 | u32 frame_count=0; | ||
526 | |||
527 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : | ||
528 | sizeof(struct megasas_sge32); | ||
529 | |||
530 | /* | ||
531 | * Main frame can contain 2 SGEs for 64-bit SGLs and | ||
532 | * 3 SGEs for 32-bit SGLs | ||
533 | */ | ||
534 | if (IS_DMA64) | ||
535 | num_cnt = sge_count - 2; | ||
536 | else | ||
537 | num_cnt = sge_count - 3; | ||
538 | |||
539 | if(num_cnt>0){ | ||
540 | sge_bytes = sge_sz * num_cnt; | ||
541 | |||
542 | frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) + | ||
543 | ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) ; | ||
544 | } | ||
545 | /* Main frame */ | ||
546 | frame_count +=1; | ||
547 | |||
548 | if (frame_count > 7) | ||
549 | frame_count = 8; | ||
550 | return frame_count; | ||
551 | } | ||
552 | |||
498 | /** | 553 | /** |
499 | * megasas_build_dcdb - Prepares a direct cdb (DCDB) command | 554 | * megasas_build_dcdb - Prepares a direct cdb (DCDB) command |
500 | * @instance: Adapter soft state | 555 | * @instance: Adapter soft state |
@@ -508,8 +563,6 @@ static int | |||
508 | megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | 563 | megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, |
509 | struct megasas_cmd *cmd) | 564 | struct megasas_cmd *cmd) |
510 | { | 565 | { |
511 | u32 sge_sz; | ||
512 | int sge_bytes; | ||
513 | u32 is_logical; | 566 | u32 is_logical; |
514 | u32 device_id; | 567 | u32 device_id; |
515 | u16 flags = 0; | 568 | u16 flags = 0; |
@@ -544,9 +597,6 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
544 | /* | 597 | /* |
545 | * Construct SGL | 598 | * Construct SGL |
546 | */ | 599 | */ |
547 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : | ||
548 | sizeof(struct megasas_sge32); | ||
549 | |||
550 | if (IS_DMA64) { | 600 | if (IS_DMA64) { |
551 | pthru->flags |= MFI_FRAME_SGL64; | 601 | pthru->flags |= MFI_FRAME_SGL64; |
552 | pthru->sge_count = megasas_make_sgl64(instance, scp, | 602 | pthru->sge_count = megasas_make_sgl64(instance, scp, |
@@ -562,17 +612,11 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
562 | pthru->sense_buf_phys_addr_hi = 0; | 612 | pthru->sense_buf_phys_addr_hi = 0; |
563 | pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr; | 613 | pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr; |
564 | 614 | ||
565 | sge_bytes = sge_sz * pthru->sge_count; | ||
566 | |||
567 | /* | 615 | /* |
568 | * Compute the total number of frames this command consumes. FW uses | 616 | * Compute the total number of frames this command consumes. FW uses |
569 | * this number to pull sufficient number of frames from host memory. | 617 | * this number to pull sufficient number of frames from host memory. |
570 | */ | 618 | */ |
571 | cmd->frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) + | 619 | cmd->frame_count = megasas_get_frame_count(pthru->sge_count); |
572 | ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) + 1; | ||
573 | |||
574 | if (cmd->frame_count > 7) | ||
575 | cmd->frame_count = 8; | ||
576 | 620 | ||
577 | return cmd->frame_count; | 621 | return cmd->frame_count; |
578 | } | 622 | } |
@@ -589,8 +633,6 @@ static int | |||
589 | megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | 633 | megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, |
590 | struct megasas_cmd *cmd) | 634 | struct megasas_cmd *cmd) |
591 | { | 635 | { |
592 | u32 sge_sz; | ||
593 | int sge_bytes; | ||
594 | u32 device_id; | 636 | u32 device_id; |
595 | u8 sc = scp->cmnd[0]; | 637 | u8 sc = scp->cmnd[0]; |
596 | u16 flags = 0; | 638 | u16 flags = 0; |
@@ -605,7 +647,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
605 | flags = MFI_FRAME_DIR_READ; | 647 | flags = MFI_FRAME_DIR_READ; |
606 | 648 | ||
607 | /* | 649 | /* |
608 | * Preare the Logical IO frame: 2nd bit is zero for all read cmds | 650 | * Prepare the Logical IO frame: 2nd bit is zero for all read cmds |
609 | */ | 651 | */ |
610 | ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ; | 652 | ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ; |
611 | ldio->cmd_status = 0x0; | 653 | ldio->cmd_status = 0x0; |
@@ -674,9 +716,6 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
674 | /* | 716 | /* |
675 | * Construct SGL | 717 | * Construct SGL |
676 | */ | 718 | */ |
677 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : | ||
678 | sizeof(struct megasas_sge32); | ||
679 | |||
680 | if (IS_DMA64) { | 719 | if (IS_DMA64) { |
681 | ldio->flags |= MFI_FRAME_SGL64; | 720 | ldio->flags |= MFI_FRAME_SGL64; |
682 | ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); | 721 | ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); |
@@ -690,13 +729,11 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
690 | ldio->sense_buf_phys_addr_hi = 0; | 729 | ldio->sense_buf_phys_addr_hi = 0; |
691 | ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr; | 730 | ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr; |
692 | 731 | ||
693 | sge_bytes = sge_sz * ldio->sge_count; | 732 | /* |
694 | 733 | * Compute the total number of frames this command consumes. FW uses | |
695 | cmd->frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) + | 734 | * this number to pull sufficient number of frames from host memory. |
696 | ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) + 1; | 735 | */ |
697 | 736 | cmd->frame_count = megasas_get_frame_count(ldio->sge_count); | |
698 | if (cmd->frame_count > 7) | ||
699 | cmd->frame_count = 8; | ||
700 | 737 | ||
701 | return cmd->frame_count; | 738 | return cmd->frame_count; |
702 | } | 739 | } |
@@ -727,6 +764,69 @@ static inline int megasas_is_ldio(struct scsi_cmnd *cmd) | |||
727 | } | 764 | } |
728 | } | 765 | } |
729 | 766 | ||
767 | /** | ||
768 | * megasas_dump_pending_frames - Dumps the frame address of all pending cmds | ||
769 | * in FW | ||
770 | * @instance: Adapter soft state | ||
771 | */ | ||
772 | static inline void | ||
773 | megasas_dump_pending_frames(struct megasas_instance *instance) | ||
774 | { | ||
775 | struct megasas_cmd *cmd; | ||
776 | int i,n; | ||
777 | union megasas_sgl *mfi_sgl; | ||
778 | struct megasas_io_frame *ldio; | ||
779 | struct megasas_pthru_frame *pthru; | ||
780 | u32 sgcount; | ||
781 | u32 max_cmd = instance->max_fw_cmds; | ||
782 | |||
783 | printk(KERN_ERR "\nmegasas[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no); | ||
784 | printk(KERN_ERR "megasas[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding)); | ||
785 | if (IS_DMA64) | ||
786 | printk(KERN_ERR "\nmegasas[%d]: 64 bit SGLs were sent to FW\n",instance->host->host_no); | ||
787 | else | ||
788 | printk(KERN_ERR "\nmegasas[%d]: 32 bit SGLs were sent to FW\n",instance->host->host_no); | ||
789 | |||
790 | printk(KERN_ERR "megasas[%d]: Pending OS cmds in FW : \n",instance->host->host_no); | ||
791 | for (i = 0; i < max_cmd; i++) { | ||
792 | cmd = instance->cmd_list[i]; | ||
793 | if(!cmd->scmd) | ||
794 | continue; | ||
795 | printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr); | ||
796 | if (megasas_is_ldio(cmd->scmd)){ | ||
797 | ldio = (struct megasas_io_frame *)cmd->frame; | ||
798 | mfi_sgl = &ldio->sgl; | ||
799 | sgcount = ldio->sge_count; | ||
800 | printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lba lo : 0x%x, lba_hi : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no, cmd->frame_count,ldio->cmd,ldio->target_id, ldio->start_lba_lo,ldio->start_lba_hi,ldio->sense_buf_phys_addr_lo,sgcount); | ||
801 | } | ||
802 | else { | ||
803 | pthru = (struct megasas_pthru_frame *) cmd->frame; | ||
804 | mfi_sgl = &pthru->sgl; | ||
805 | sgcount = pthru->sge_count; | ||
806 | printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lun : 0x%x, cdb_len : 0x%x, data xfer len : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no,cmd->frame_count,pthru->cmd,pthru->target_id,pthru->lun,pthru->cdb_len , pthru->data_xfer_len,pthru->sense_buf_phys_addr_lo,sgcount); | ||
807 | } | ||
808 | if(megasas_dbg_lvl & MEGASAS_DBG_LVL){ | ||
809 | for (n = 0; n < sgcount; n++){ | ||
810 | if (IS_DMA64) | ||
811 | printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%08lx ",mfi_sgl->sge64[n].length , (unsigned long)mfi_sgl->sge64[n].phys_addr) ; | ||
812 | else | ||
813 | printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%x ",mfi_sgl->sge32[n].length , mfi_sgl->sge32[n].phys_addr) ; | ||
814 | } | ||
815 | } | ||
816 | printk(KERN_ERR "\n"); | ||
817 | } /*for max_cmd*/ | ||
818 | printk(KERN_ERR "\nmegasas[%d]: Pending Internal cmds in FW : \n",instance->host->host_no); | ||
819 | for (i = 0; i < max_cmd; i++) { | ||
820 | |||
821 | cmd = instance->cmd_list[i]; | ||
822 | |||
823 | if(cmd->sync_cmd == 1){ | ||
824 | printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr); | ||
825 | } | ||
826 | } | ||
827 | printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no); | ||
828 | } | ||
829 | |||
730 | /** | 830 | /** |
731 | * megasas_queue_command - Queue entry point | 831 | * megasas_queue_command - Queue entry point |
732 | * @scmd: SCSI command to be queued | 832 | * @scmd: SCSI command to be queued |
@@ -832,6 +932,13 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) | |||
832 | } | 932 | } |
833 | 933 | ||
834 | if (atomic_read(&instance->fw_outstanding)) { | 934 | if (atomic_read(&instance->fw_outstanding)) { |
935 | /* | ||
936 | * Send signal to FW to stop processing any pending cmds. | ||
937 | * The controller will be taken offline by the OS now. | ||
938 | */ | ||
939 | writel(MFI_STOP_ADP, | ||
940 | &instance->reg_set->inbound_doorbell); | ||
941 | megasas_dump_pending_frames(instance); | ||
835 | instance->hw_crit_error = 1; | 942 | instance->hw_crit_error = 1; |
836 | return FAILED; | 943 | return FAILED; |
837 | } | 944 | } |
@@ -1168,11 +1275,6 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | |||
1168 | static int | 1275 | static int |
1169 | megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) | 1276 | megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) |
1170 | { | 1277 | { |
1171 | u32 producer; | ||
1172 | u32 consumer; | ||
1173 | u32 context; | ||
1174 | struct megasas_cmd *cmd; | ||
1175 | |||
1176 | /* | 1278 | /* |
1177 | * Check if it is our interrupt | 1279 | * Check if it is our interrupt |
1178 | * Clear the interrupt | 1280 | * Clear the interrupt |
@@ -1180,23 +1282,10 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) | |||
1180 | if(instance->instancet->clear_intr(instance->reg_set)) | 1282 | if(instance->instancet->clear_intr(instance->reg_set)) |
1181 | return IRQ_NONE; | 1283 | return IRQ_NONE; |
1182 | 1284 | ||
1183 | producer = *instance->producer; | 1285 | /* |
1184 | consumer = *instance->consumer; | 1286 | * Schedule the tasklet for cmd completion |
1185 | 1287 | */ | |
1186 | while (consumer != producer) { | 1288 | tasklet_schedule(&instance->isr_tasklet); |
1187 | context = instance->reply_queue[consumer]; | ||
1188 | |||
1189 | cmd = instance->cmd_list[context]; | ||
1190 | |||
1191 | megasas_complete_cmd(instance, cmd, alt_status); | ||
1192 | |||
1193 | consumer++; | ||
1194 | if (consumer == (instance->max_fw_cmds + 1)) { | ||
1195 | consumer = 0; | ||
1196 | } | ||
1197 | } | ||
1198 | |||
1199 | *instance->consumer = producer; | ||
1200 | 1289 | ||
1201 | return IRQ_HANDLED; | 1290 | return IRQ_HANDLED; |
1202 | } | 1291 | } |
@@ -1229,10 +1318,12 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1229 | 1318 | ||
1230 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; | 1319 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; |
1231 | 1320 | ||
1321 | if (fw_state != MFI_STATE_READY) | ||
1322 | printk(KERN_INFO "megasas: Waiting for FW to come to ready" | ||
1323 | " state\n"); | ||
1324 | |||
1232 | while (fw_state != MFI_STATE_READY) { | 1325 | while (fw_state != MFI_STATE_READY) { |
1233 | 1326 | ||
1234 | printk(KERN_INFO "megasas: Waiting for FW to come to ready" | ||
1235 | " state\n"); | ||
1236 | switch (fw_state) { | 1327 | switch (fw_state) { |
1237 | 1328 | ||
1238 | case MFI_STATE_FAULT: | 1329 | case MFI_STATE_FAULT: |
@@ -1244,19 +1335,27 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1244 | /* | 1335 | /* |
1245 | * Set the CLR bit in inbound doorbell | 1336 | * Set the CLR bit in inbound doorbell |
1246 | */ | 1337 | */ |
1247 | writel(MFI_INIT_CLEAR_HANDSHAKE, | 1338 | writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, |
1248 | &instance->reg_set->inbound_doorbell); | 1339 | &instance->reg_set->inbound_doorbell); |
1249 | 1340 | ||
1250 | max_wait = 2; | 1341 | max_wait = 2; |
1251 | cur_state = MFI_STATE_WAIT_HANDSHAKE; | 1342 | cur_state = MFI_STATE_WAIT_HANDSHAKE; |
1252 | break; | 1343 | break; |
1253 | 1344 | ||
1345 | case MFI_STATE_BOOT_MESSAGE_PENDING: | ||
1346 | writel(MFI_INIT_HOTPLUG, | ||
1347 | &instance->reg_set->inbound_doorbell); | ||
1348 | |||
1349 | max_wait = 10; | ||
1350 | cur_state = MFI_STATE_BOOT_MESSAGE_PENDING; | ||
1351 | break; | ||
1352 | |||
1254 | case MFI_STATE_OPERATIONAL: | 1353 | case MFI_STATE_OPERATIONAL: |
1255 | /* | 1354 | /* |
1256 | * Bring it to READY state; assuming max wait 2 secs | 1355 | * Bring it to READY state; assuming max wait 10 secs |
1257 | */ | 1356 | */ |
1258 | megasas_disable_intr(instance); | 1357 | instance->instancet->disable_intr(instance->reg_set); |
1259 | writel(MFI_INIT_READY, &instance->reg_set->inbound_doorbell); | 1358 | writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell); |
1260 | 1359 | ||
1261 | max_wait = 10; | 1360 | max_wait = 10; |
1262 | cur_state = MFI_STATE_OPERATIONAL; | 1361 | cur_state = MFI_STATE_OPERATIONAL; |
@@ -1323,6 +1422,7 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1323 | return -ENODEV; | 1422 | return -ENODEV; |
1324 | } | 1423 | } |
1325 | }; | 1424 | }; |
1425 | printk(KERN_INFO "megasas: FW now in Ready state\n"); | ||
1326 | 1426 | ||
1327 | return 0; | 1427 | return 0; |
1328 | } | 1428 | } |
@@ -1352,7 +1452,7 @@ static void megasas_teardown_frame_pool(struct megasas_instance *instance) | |||
1352 | cmd->frame_phys_addr); | 1452 | cmd->frame_phys_addr); |
1353 | 1453 | ||
1354 | if (cmd->sense) | 1454 | if (cmd->sense) |
1355 | pci_pool_free(instance->sense_dma_pool, cmd->frame, | 1455 | pci_pool_free(instance->sense_dma_pool, cmd->sense, |
1356 | cmd->sense_phys_addr); | 1456 | cmd->sense_phys_addr); |
1357 | } | 1457 | } |
1358 | 1458 | ||
@@ -1628,6 +1728,39 @@ megasas_get_ctrl_info(struct megasas_instance *instance, | |||
1628 | } | 1728 | } |
1629 | 1729 | ||
1630 | /** | 1730 | /** |
1731 | * megasas_complete_cmd_dpc - Returns FW's controller structure | ||
1732 | * @instance_addr: Address of adapter soft state | ||
1733 | * | ||
1734 | * Tasklet to complete cmds | ||
1735 | */ | ||
1736 | void megasas_complete_cmd_dpc(unsigned long instance_addr) | ||
1737 | { | ||
1738 | u32 producer; | ||
1739 | u32 consumer; | ||
1740 | u32 context; | ||
1741 | struct megasas_cmd *cmd; | ||
1742 | struct megasas_instance *instance = (struct megasas_instance *)instance_addr; | ||
1743 | |||
1744 | producer = *instance->producer; | ||
1745 | consumer = *instance->consumer; | ||
1746 | |||
1747 | while (consumer != producer) { | ||
1748 | context = instance->reply_queue[consumer]; | ||
1749 | |||
1750 | cmd = instance->cmd_list[context]; | ||
1751 | |||
1752 | megasas_complete_cmd(instance, cmd, DID_OK); | ||
1753 | |||
1754 | consumer++; | ||
1755 | if (consumer == (instance->max_fw_cmds + 1)) { | ||
1756 | consumer = 0; | ||
1757 | } | ||
1758 | } | ||
1759 | |||
1760 | *instance->consumer = producer; | ||
1761 | } | ||
1762 | |||
1763 | /** | ||
1631 | * megasas_init_mfi - Initializes the FW | 1764 | * megasas_init_mfi - Initializes the FW |
1632 | * @instance: Adapter soft state | 1765 | * @instance: Adapter soft state |
1633 | * | 1766 | * |
@@ -1690,6 +1823,12 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
1690 | * Get various operational parameters from status register | 1823 | * Get various operational parameters from status register |
1691 | */ | 1824 | */ |
1692 | instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; | 1825 | instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; |
1826 | /* | ||
1827 | * Reduce the max supported cmds by 1. This is to ensure that the | ||
1828 | * reply_q_sz (1 more than the max cmd that driver may send) | ||
1829 | * does not exceed max cmds that the FW can support | ||
1830 | */ | ||
1831 | instance->max_fw_cmds = instance->max_fw_cmds-1; | ||
1693 | instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> | 1832 | instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> |
1694 | 0x10; | 1833 | 0x10; |
1695 | /* | 1834 | /* |
@@ -1754,7 +1893,7 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
1754 | /* | 1893 | /* |
1755 | * disable the intr before firing the init frame to FW | 1894 | * disable the intr before firing the init frame to FW |
1756 | */ | 1895 | */ |
1757 | megasas_disable_intr(instance); | 1896 | instance->instancet->disable_intr(instance->reg_set); |
1758 | 1897 | ||
1759 | /* | 1898 | /* |
1760 | * Issue the init frame in polled mode | 1899 | * Issue the init frame in polled mode |
@@ -1791,6 +1930,12 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
1791 | 1930 | ||
1792 | kfree(ctrl_info); | 1931 | kfree(ctrl_info); |
1793 | 1932 | ||
1933 | /* | ||
1934 | * Setup tasklet for cmd completion | ||
1935 | */ | ||
1936 | |||
1937 | tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, | ||
1938 | (unsigned long)instance); | ||
1794 | return 0; | 1939 | return 0; |
1795 | 1940 | ||
1796 | fail_fw_init: | 1941 | fail_fw_init: |
@@ -2182,6 +2327,8 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2182 | instance->unique_id = pdev->bus->number << 8 | pdev->devfn; | 2327 | instance->unique_id = pdev->bus->number << 8 | pdev->devfn; |
2183 | instance->init_id = MEGASAS_DEFAULT_INIT_ID; | 2328 | instance->init_id = MEGASAS_DEFAULT_INIT_ID; |
2184 | 2329 | ||
2330 | megasas_dbg_lvl = 0; | ||
2331 | |||
2185 | /* | 2332 | /* |
2186 | * Initialize MFI Firmware | 2333 | * Initialize MFI Firmware |
2187 | */ | 2334 | */ |
@@ -2234,7 +2381,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2234 | megasas_mgmt_info.max_index--; | 2381 | megasas_mgmt_info.max_index--; |
2235 | 2382 | ||
2236 | pci_set_drvdata(pdev, NULL); | 2383 | pci_set_drvdata(pdev, NULL); |
2237 | megasas_disable_intr(instance); | 2384 | instance->instancet->disable_intr(instance->reg_set); |
2238 | free_irq(instance->pdev->irq, instance); | 2385 | free_irq(instance->pdev->irq, instance); |
2239 | 2386 | ||
2240 | megasas_release_mfi(instance); | 2387 | megasas_release_mfi(instance); |
@@ -2348,6 +2495,7 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
2348 | scsi_remove_host(instance->host); | 2495 | scsi_remove_host(instance->host); |
2349 | megasas_flush_cache(instance); | 2496 | megasas_flush_cache(instance); |
2350 | megasas_shutdown_controller(instance); | 2497 | megasas_shutdown_controller(instance); |
2498 | tasklet_kill(&instance->isr_tasklet); | ||
2351 | 2499 | ||
2352 | /* | 2500 | /* |
2353 | * Take the instance off the instance array. Note that we will not | 2501 | * Take the instance off the instance array. Note that we will not |
@@ -2364,7 +2512,7 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
2364 | 2512 | ||
2365 | pci_set_drvdata(instance->pdev, NULL); | 2513 | pci_set_drvdata(instance->pdev, NULL); |
2366 | 2514 | ||
2367 | megasas_disable_intr(instance); | 2515 | instance->instancet->disable_intr(instance->reg_set); |
2368 | 2516 | ||
2369 | free_irq(instance->pdev->irq, instance); | 2517 | free_irq(instance->pdev->irq, instance); |
2370 | 2518 | ||
@@ -2716,7 +2864,8 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) | |||
2716 | int i; | 2864 | int i; |
2717 | int error = 0; | 2865 | int error = 0; |
2718 | 2866 | ||
2719 | clear_user(ioc, sizeof(*ioc)); | 2867 | if (clear_user(ioc, sizeof(*ioc))) |
2868 | return -EFAULT; | ||
2720 | 2869 | ||
2721 | if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) || | 2870 | if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) || |
2722 | copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) || | 2871 | copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) || |
@@ -2808,6 +2957,26 @@ megasas_sysfs_show_release_date(struct device_driver *dd, char *buf) | |||
2808 | static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date, | 2957 | static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date, |
2809 | NULL); | 2958 | NULL); |
2810 | 2959 | ||
2960 | static ssize_t | ||
2961 | megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf) | ||
2962 | { | ||
2963 | return sprintf(buf,"%u",megasas_dbg_lvl); | ||
2964 | } | ||
2965 | |||
2966 | static ssize_t | ||
2967 | megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t count) | ||
2968 | { | ||
2969 | int retval = count; | ||
2970 | if(sscanf(buf,"%u",&megasas_dbg_lvl)<1){ | ||
2971 | printk(KERN_ERR "megasas: could not set dbg_lvl\n"); | ||
2972 | retval = -EINVAL; | ||
2973 | } | ||
2974 | return retval; | ||
2975 | } | ||
2976 | |||
2977 | static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl, | ||
2978 | megasas_sysfs_set_dbg_lvl); | ||
2979 | |||
2811 | /** | 2980 | /** |
2812 | * megasas_init - Driver load entry point | 2981 | * megasas_init - Driver load entry point |
2813 | */ | 2982 | */ |
@@ -2842,14 +3011,33 @@ static int __init megasas_init(void) | |||
2842 | 3011 | ||
2843 | if (rval) { | 3012 | if (rval) { |
2844 | printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n"); | 3013 | printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n"); |
2845 | unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); | 3014 | goto err_pcidrv; |
2846 | } | 3015 | } |
2847 | 3016 | ||
2848 | driver_create_file(&megasas_pci_driver.driver, &driver_attr_version); | 3017 | rval = driver_create_file(&megasas_pci_driver.driver, |
2849 | driver_create_file(&megasas_pci_driver.driver, | 3018 | &driver_attr_version); |
2850 | &driver_attr_release_date); | 3019 | if (rval) |
3020 | goto err_dcf_attr_ver; | ||
3021 | rval = driver_create_file(&megasas_pci_driver.driver, | ||
3022 | &driver_attr_release_date); | ||
3023 | if (rval) | ||
3024 | goto err_dcf_rel_date; | ||
3025 | rval = driver_create_file(&megasas_pci_driver.driver, | ||
3026 | &driver_attr_dbg_lvl); | ||
3027 | if (rval) | ||
3028 | goto err_dcf_dbg_lvl; | ||
2851 | 3029 | ||
2852 | return rval; | 3030 | return rval; |
3031 | err_dcf_dbg_lvl: | ||
3032 | driver_remove_file(&megasas_pci_driver.driver, | ||
3033 | &driver_attr_release_date); | ||
3034 | err_dcf_rel_date: | ||
3035 | driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); | ||
3036 | err_dcf_attr_ver: | ||
3037 | pci_unregister_driver(&megasas_pci_driver); | ||
3038 | err_pcidrv: | ||
3039 | unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); | ||
3040 | return rval; | ||
2853 | } | 3041 | } |
2854 | 3042 | ||
2855 | /** | 3043 | /** |
@@ -2857,9 +3045,11 @@ static int __init megasas_init(void) | |||
2857 | */ | 3045 | */ |
2858 | static void __exit megasas_exit(void) | 3046 | static void __exit megasas_exit(void) |
2859 | { | 3047 | { |
2860 | driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); | 3048 | driver_remove_file(&megasas_pci_driver.driver, |
3049 | &driver_attr_dbg_lvl); | ||
2861 | driver_remove_file(&megasas_pci_driver.driver, | 3050 | driver_remove_file(&megasas_pci_driver.driver, |
2862 | &driver_attr_release_date); | 3051 | &driver_attr_release_date); |
3052 | driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); | ||
2863 | 3053 | ||
2864 | pci_unregister_driver(&megasas_pci_driver); | 3054 | pci_unregister_driver(&megasas_pci_driver); |
2865 | unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); | 3055 | unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); |