diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/mvsas.c | 123 |
1 files changed, 87 insertions, 36 deletions
diff --git a/drivers/scsi/mvsas.c b/drivers/scsi/mvsas.c index 5ec0665b3a3d..3a447fea0b1f 100644 --- a/drivers/scsi/mvsas.c +++ b/drivers/scsi/mvsas.c | |||
@@ -37,11 +37,13 @@ | |||
37 | #include <linux/dma-mapping.h> | 37 | #include <linux/dma-mapping.h> |
38 | #include <linux/ctype.h> | 38 | #include <linux/ctype.h> |
39 | #include <scsi/libsas.h> | 39 | #include <scsi/libsas.h> |
40 | #include <scsi/scsi_tcq.h> | ||
41 | #include <scsi/sas_ata.h> | ||
40 | #include <asm/io.h> | 42 | #include <asm/io.h> |
41 | 43 | ||
42 | #define DRV_NAME "mvsas" | 44 | #define DRV_NAME "mvsas" |
43 | #define DRV_VERSION "0.5.1" | 45 | #define DRV_VERSION "0.5.2" |
44 | #define _MV_DUMP 0 | 46 | #define _MV_DUMP 0 |
45 | #define MVS_DISABLE_NVRAM | 47 | #define MVS_DISABLE_NVRAM |
46 | #define MVS_DISABLE_MSI | 48 | #define MVS_DISABLE_MSI |
47 | 49 | ||
@@ -52,7 +54,7 @@ | |||
52 | readl(regs + MVS_##reg); \ | 54 | readl(regs + MVS_##reg); \ |
53 | } while (0) | 55 | } while (0) |
54 | 56 | ||
55 | #define MVS_ID_NOT_MAPPED 0xff | 57 | #define MVS_ID_NOT_MAPPED 0x7f |
56 | #define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width) | 58 | #define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width) |
57 | 59 | ||
58 | /* offset for D2H FIS in the Received FIS List Structure */ | 60 | /* offset for D2H FIS in the Received FIS List Structure */ |
@@ -84,6 +86,7 @@ enum driver_configuration { | |||
84 | MVS_RX_FIS_COUNT = 17, /* Optional rx'd FISs (max 17) */ | 86 | MVS_RX_FIS_COUNT = 17, /* Optional rx'd FISs (max 17) */ |
85 | 87 | ||
86 | MVS_QUEUE_SIZE = 30, /* Support Queue depth */ | 88 | MVS_QUEUE_SIZE = 30, /* Support Queue depth */ |
89 | MVS_CAN_QUEUE = MVS_SLOTS - 1, /* SCSI Queue depth */ | ||
87 | }; | 90 | }; |
88 | 91 | ||
89 | /* unchangeable hardware details */ | 92 | /* unchangeable hardware details */ |
@@ -358,7 +361,20 @@ enum hw_register_bits { | |||
358 | 361 | ||
359 | /* VSR */ | 362 | /* VSR */ |
360 | /* PHYMODE 6 (CDB) */ | 363 | /* PHYMODE 6 (CDB) */ |
361 | PHY_MODE6_DTL_SPEED = (1U << 27), | 364 | PHY_MODE6_LATECLK = (1U << 29), /* Lock Clock */ |
365 | PHY_MODE6_DTL_SPEED = (1U << 27), /* Digital Loop Speed */ | ||
366 | PHY_MODE6_FC_ORDER = (1U << 26), /* Fibre Channel Mode Order*/ | ||
367 | PHY_MODE6_MUCNT_EN = (1U << 24), /* u Count Enable */ | ||
368 | PHY_MODE6_SEL_MUCNT_LEN = (1U << 22), /* Training Length Select */ | ||
369 | PHY_MODE6_SELMUPI = (1U << 20), /* Phase Multi Select (init) */ | ||
370 | PHY_MODE6_SELMUPF = (1U << 18), /* Phase Multi Select (final) */ | ||
371 | PHY_MODE6_SELMUFF = (1U << 16), /* Freq Loop Multi Sel(final) */ | ||
372 | PHY_MODE6_SELMUFI = (1U << 14), /* Freq Loop Multi Sel(init) */ | ||
373 | PHY_MODE6_FREEZE_LOOP = (1U << 12), /* Freeze Rx CDR Loop */ | ||
374 | PHY_MODE6_INT_RXFOFFS = (1U << 3), /* Rx CDR Freq Loop Enable */ | ||
375 | PHY_MODE6_FRC_RXFOFFS = (1U << 2), /* Initial Rx CDR Offset */ | ||
376 | PHY_MODE6_STAU_0D8 = (1U << 1), /* Rx CDR Freq Loop Saturate */ | ||
377 | PHY_MODE6_RXSAT_DIS = (1U << 0), /* Saturate Ctl */ | ||
362 | }; | 378 | }; |
363 | 379 | ||
364 | enum mvs_info_flags { | 380 | enum mvs_info_flags { |
@@ -511,7 +527,43 @@ enum status_buffer { | |||
511 | }; | 527 | }; |
512 | 528 | ||
513 | enum error_info_rec { | 529 | enum error_info_rec { |
514 | CMD_ISS_STPD = (1U << 31), /* Cmd Issue Stopped */ | 530 | CMD_ISS_STPD = (1U << 31), /* Cmd Issue Stopped */ |
531 | CMD_PI_ERR = (1U << 30), /* Protection info error. see flags2 */ | ||
532 | RSP_OVER = (1U << 29), /* rsp buffer overflow */ | ||
533 | RETRY_LIM = (1U << 28), /* FIS/frame retry limit exceeded */ | ||
534 | UNK_FIS = (1U << 27), /* unknown FIS */ | ||
535 | DMA_TERM = (1U << 26), /* DMA terminate primitive rx'd */ | ||
536 | SYNC_ERR = (1U << 25), /* SYNC rx'd during frame xmit */ | ||
537 | TFILE_ERR = (1U << 24), /* SATA taskfile Error bit set */ | ||
538 | R_ERR = (1U << 23), /* SATA returned R_ERR prim */ | ||
539 | RD_OFS = (1U << 20), /* Read DATA frame invalid offset */ | ||
540 | XFER_RDY_OFS = (1U << 19), /* XFER_RDY offset error */ | ||
541 | UNEXP_XFER_RDY = (1U << 18), /* unexpected XFER_RDY error */ | ||
542 | DATA_OVER_UNDER = (1U << 16), /* data overflow/underflow */ | ||
543 | INTERLOCK = (1U << 15), /* interlock error */ | ||
544 | NAK = (1U << 14), /* NAK rx'd */ | ||
545 | ACK_NAK_TO = (1U << 13), /* ACK/NAK timeout */ | ||
546 | CXN_CLOSED = (1U << 12), /* cxn closed w/out ack/nak */ | ||
547 | OPEN_TO = (1U << 11), /* I_T nexus lost, open cxn timeout */ | ||
548 | PATH_BLOCKED = (1U << 10), /* I_T nexus lost, pathway blocked */ | ||
549 | NO_DEST = (1U << 9), /* I_T nexus lost, no destination */ | ||
550 | STP_RES_BSY = (1U << 8), /* STP resources busy */ | ||
551 | BREAK = (1U << 7), /* break received */ | ||
552 | BAD_DEST = (1U << 6), /* bad destination */ | ||
553 | BAD_PROTO = (1U << 5), /* protocol not supported */ | ||
554 | BAD_RATE = (1U << 4), /* cxn rate not supported */ | ||
555 | WRONG_DEST = (1U << 3), /* wrong destination error */ | ||
556 | CREDIT_TO = (1U << 2), /* credit timeout */ | ||
557 | WDOG_TO = (1U << 1), /* watchdog timeout */ | ||
558 | BUF_PAR = (1U << 0), /* buffer parity error */ | ||
559 | }; | ||
560 | |||
561 | enum error_info_rec_2 { | ||
562 | SLOT_BSY_ERR = (1U << 31), /* Slot Busy Error */ | ||
563 | GRD_CHK_ERR = (1U << 14), /* Guard Check Error */ | ||
564 | APP_CHK_ERR = (1U << 13), /* Application Check error */ | ||
565 | REF_CHK_ERR = (1U << 12), /* Reference Check Error */ | ||
566 | USR_BLK_NM = (1U << 0), /* User Block Number */ | ||
515 | }; | 567 | }; |
516 | 568 | ||
517 | struct mvs_chip_info { | 569 | struct mvs_chip_info { |
@@ -543,28 +595,12 @@ struct mvs_cmd_hdr { | |||
543 | __le32 reserved[4]; | 595 | __le32 reserved[4]; |
544 | }; | 596 | }; |
545 | 597 | ||
546 | struct mvs_slot_info { | ||
547 | struct sas_task *task; | ||
548 | u32 n_elem; | ||
549 | u32 tx; | ||
550 | |||
551 | /* DMA buffer for storing cmd tbl, open addr frame, status buffer, | ||
552 | * and PRD table | ||
553 | */ | ||
554 | void *buf; | ||
555 | dma_addr_t buf_dma; | ||
556 | #if _MV_DUMP | ||
557 | u32 cmd_size; | ||
558 | #endif | ||
559 | |||
560 | void *response; | ||
561 | }; | ||
562 | |||
563 | struct mvs_port { | 598 | struct mvs_port { |
564 | struct asd_sas_port sas_port; | 599 | struct asd_sas_port sas_port; |
565 | u8 port_attached; | 600 | u8 port_attached; |
566 | u8 taskfileset; | 601 | u8 taskfileset; |
567 | u8 wide_port_phymap; | 602 | u8 wide_port_phymap; |
603 | struct list_head list; | ||
568 | }; | 604 | }; |
569 | 605 | ||
570 | struct mvs_phy { | 606 | struct mvs_phy { |
@@ -582,6 +618,27 @@ struct mvs_phy { | |||
582 | u32 frame_rcvd_size; | 618 | u32 frame_rcvd_size; |
583 | u8 frame_rcvd[32]; | 619 | u8 frame_rcvd[32]; |
584 | u8 phy_attached; | 620 | u8 phy_attached; |
621 | enum sas_linkrate minimum_linkrate; | ||
622 | enum sas_linkrate maximum_linkrate; | ||
623 | }; | ||
624 | |||
625 | struct mvs_slot_info { | ||
626 | struct list_head list; | ||
627 | struct sas_task *task; | ||
628 | u32 n_elem; | ||
629 | u32 tx; | ||
630 | |||
631 | /* DMA buffer for storing cmd tbl, open addr frame, status buffer, | ||
632 | * and PRD table | ||
633 | */ | ||
634 | void *buf; | ||
635 | dma_addr_t buf_dma; | ||
636 | #if _MV_DUMP | ||
637 | u32 cmd_size; | ||
638 | #endif | ||
639 | |||
640 | void *response; | ||
641 | struct mvs_port *port; | ||
585 | }; | 642 | }; |
586 | 643 | ||
587 | struct mvs_info { | 644 | struct mvs_info { |
@@ -612,21 +669,14 @@ struct mvs_info { | |||
612 | 669 | ||
613 | const struct mvs_chip_info *chip; | 670 | const struct mvs_chip_info *chip; |
614 | 671 | ||
615 | unsigned long tags[MVS_SLOTS]; | 672 | u8 tags[MVS_SLOTS]; |
616 | struct mvs_slot_info slot_info[MVS_SLOTS]; | 673 | struct mvs_slot_info slot_info[MVS_SLOTS]; |
617 | /* further per-slot information */ | 674 | /* further per-slot information */ |
618 | struct mvs_phy phy[MVS_MAX_PHYS]; | 675 | struct mvs_phy phy[MVS_MAX_PHYS]; |
619 | struct mvs_port port[MVS_MAX_PHYS]; | 676 | struct mvs_port port[MVS_MAX_PHYS]; |
620 | 677 | #ifdef MVS_USE_TASKLET | |
621 | u32 can_queue; /* per adapter */ | 678 | struct tasklet_struct tasklet; |
622 | u32 tag_out; /*Get*/ | 679 | #endif |
623 | u32 tag_in; /*Give*/ | ||
624 | }; | ||
625 | |||
626 | struct mvs_queue_task { | ||
627 | struct list_head list; | ||
628 | |||
629 | void *uldd_task; | ||
630 | }; | 680 | }; |
631 | 681 | ||
632 | static int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, | 682 | static int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, |
@@ -641,10 +691,11 @@ static u32 mvs_read_port_irq_mask(struct mvs_info *mvi, u32 port); | |||
641 | static u32 mvs_is_phy_ready(struct mvs_info *mvi, int i); | 691 | static u32 mvs_is_phy_ready(struct mvs_info *mvi, int i); |
642 | static void mvs_detect_porttype(struct mvs_info *mvi, int i); | 692 | static void mvs_detect_porttype(struct mvs_info *mvi, int i); |
643 | static void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st); | 693 | static void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st); |
694 | static void mvs_release_task(struct mvs_info *mvi, int phy_no); | ||
644 | 695 | ||
645 | static int mvs_scan_finished(struct Scsi_Host *, unsigned long); | 696 | static int mvs_scan_finished(struct Scsi_Host *, unsigned long); |
646 | static void mvs_scan_start(struct Scsi_Host *); | 697 | static void mvs_scan_start(struct Scsi_Host *); |
647 | static int mvs_sas_slave_alloc(struct scsi_device *scsi_dev); | 698 | static int mvs_slave_configure(struct scsi_device *sdev); |
648 | 699 | ||
649 | static struct scsi_transport_template *mvs_stt; | 700 | static struct scsi_transport_template *mvs_stt; |
650 | 701 | ||
@@ -659,7 +710,7 @@ static struct scsi_host_template mvs_sht = { | |||
659 | .name = DRV_NAME, | 710 | .name = DRV_NAME, |
660 | .queuecommand = sas_queuecommand, | 711 | .queuecommand = sas_queuecommand, |
661 | .target_alloc = sas_target_alloc, | 712 | .target_alloc = sas_target_alloc, |
662 | .slave_configure = sas_slave_configure, | 713 | .slave_configure = mvs_slave_configure, |
663 | .slave_destroy = sas_slave_destroy, | 714 | .slave_destroy = sas_slave_destroy, |
664 | .scan_finished = mvs_scan_finished, | 715 | .scan_finished = mvs_scan_finished, |
665 | .scan_start = mvs_scan_start, | 716 | .scan_start = mvs_scan_start, |
@@ -674,7 +725,7 @@ static struct scsi_host_template mvs_sht = { | |||
674 | .use_clustering = ENABLE_CLUSTERING, | 725 | .use_clustering = ENABLE_CLUSTERING, |
675 | .eh_device_reset_handler = sas_eh_device_reset_handler, | 726 | .eh_device_reset_handler = sas_eh_device_reset_handler, |
676 | .eh_bus_reset_handler = sas_eh_bus_reset_handler, | 727 | .eh_bus_reset_handler = sas_eh_bus_reset_handler, |
677 | .slave_alloc = mvs_sas_slave_alloc, | 728 | .slave_alloc = sas_slave_alloc, |
678 | .target_destroy = sas_target_destroy, | 729 | .target_destroy = sas_target_destroy, |
679 | .ioctl = sas_ioctl, | 730 | .ioctl = sas_ioctl, |
680 | }; | 731 | }; |