diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-10-27 13:38:00 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-11 19:22:33 -0500 |
commit | 76bb24efdc5de8eead0ccc07ec7e3b59a4ca0f15 (patch) | |
tree | 989311bb1be4a8331407bb6d3d67e5bd95e8a7a6 | |
parent | a8adb83208020c913f010cb4e26d09e25300db8e (diff) |
[SCSI] lpfc 8.2.3 : Internal loopback fixes
Internal loopback fixes:
- Use HBQs rather than Q_RING_BUFF
- Correct HBQs continuation entries
- Update CT handler to SLI3 iocbs
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 7 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 31 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 123 |
4 files changed, 153 insertions, 13 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 636a930a5739..46ccdffb46aa 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -68,6 +68,7 @@ struct lpfc_dmabuf { | |||
68 | struct list_head list; | 68 | struct list_head list; |
69 | void *virt; /* virtual address ptr */ | 69 | void *virt; /* virtual address ptr */ |
70 | dma_addr_t phys; /* mapped address */ | 70 | dma_addr_t phys; /* mapped address */ |
71 | uint32_t buffer_tag; /* used for tagged queue ring */ | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | struct lpfc_dma_pool { | 74 | struct lpfc_dma_pool { |
@@ -582,6 +583,12 @@ struct lpfc_hba { | |||
582 | unsigned long last_completion_time; | 583 | unsigned long last_completion_time; |
583 | struct timer_list hb_tmofunc; | 584 | struct timer_list hb_tmofunc; |
584 | uint8_t hb_outstanding; | 585 | uint8_t hb_outstanding; |
586 | /* | ||
587 | * Following bit will be set for all buffer tags which are not | ||
588 | * associated with any HBQ. | ||
589 | */ | ||
590 | #define QUE_BUFTAG_BIT (1<<31) | ||
591 | uint32_t buffer_tag_count; | ||
585 | }; | 592 | }; |
586 | 593 | ||
587 | static inline struct Scsi_Host * | 594 | static inline struct Scsi_Host * |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 338b5dd10a92..87bea176ac05 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -211,6 +211,11 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, | |||
211 | struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, | 211 | struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, |
212 | struct lpfc_sli_ring *, | 212 | struct lpfc_sli_ring *, |
213 | dma_addr_t); | 213 | dma_addr_t); |
214 | |||
215 | uint32_t lpfc_sli_get_buffer_tag(struct lpfc_hba *); | ||
216 | struct lpfc_dmabuf * lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *, | ||
217 | struct lpfc_sli_ring *, uint32_t ); | ||
218 | |||
214 | int lpfc_sli_hbq_count(void); | 219 | int lpfc_sli_hbq_count(void); |
215 | int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t); | 220 | int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t); |
216 | int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t); | 221 | int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t); |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 8635b9294640..b61e45a1310d 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -1373,6 +1373,7 @@ typedef struct { /* FireFly BIU registers */ | |||
1373 | #define CMD_FCP_TRECEIVE64_CX 0xA1 | 1373 | #define CMD_FCP_TRECEIVE64_CX 0xA1 |
1374 | #define CMD_FCP_TRSP64_CX 0xA3 | 1374 | #define CMD_FCP_TRSP64_CX 0xA3 |
1375 | 1375 | ||
1376 | #define CMD_QUE_XRI64_CX 0xB3 | ||
1376 | #define CMD_IOCB_RCV_SEQ64_CX 0xB5 | 1377 | #define CMD_IOCB_RCV_SEQ64_CX 0xB5 |
1377 | #define CMD_IOCB_RCV_ELS64_CX 0xB7 | 1378 | #define CMD_IOCB_RCV_ELS64_CX 0xB7 |
1378 | #define CMD_IOCB_RCV_CONT64_CX 0xBB | 1379 | #define CMD_IOCB_RCV_CONT64_CX 0xBB |
@@ -3039,7 +3040,26 @@ struct rcv_sli3 { | |||
3039 | struct ulp_bde64 bde2; | 3040 | struct ulp_bde64 bde2; |
3040 | }; | 3041 | }; |
3041 | 3042 | ||
3043 | /* Structure used for a single HBQ entry */ | ||
3044 | struct lpfc_hbq_entry { | ||
3045 | struct ulp_bde64 bde; | ||
3046 | uint32_t buffer_tag; | ||
3047 | }; | ||
3042 | 3048 | ||
3049 | /* IOCB Command template for QUE_XRI64_CX (0xB3) command */ | ||
3050 | typedef struct { | ||
3051 | struct lpfc_hbq_entry buff; | ||
3052 | uint32_t rsvd; | ||
3053 | uint32_t rsvd1; | ||
3054 | } QUE_XRI64_CX_FIELDS; | ||
3055 | |||
3056 | struct que_xri64cx_ext_fields { | ||
3057 | uint32_t iotag64_low; | ||
3058 | uint32_t iotag64_high; | ||
3059 | uint32_t ebde_count; | ||
3060 | uint32_t rsvd; | ||
3061 | struct lpfc_hbq_entry buff[5]; | ||
3062 | }; | ||
3043 | 3063 | ||
3044 | typedef struct _IOCB { /* IOCB structure */ | 3064 | typedef struct _IOCB { /* IOCB structure */ |
3045 | union { | 3065 | union { |
@@ -3064,6 +3084,7 @@ typedef struct _IOCB { /* IOCB structure */ | |||
3064 | FCPI_FIELDS64 fcpi64; /* FCP 64 bit Initiator template */ | 3084 | FCPI_FIELDS64 fcpi64; /* FCP 64 bit Initiator template */ |
3065 | FCPT_FIELDS64 fcpt64; /* FCP 64 bit target template */ | 3085 | FCPT_FIELDS64 fcpt64; /* FCP 64 bit target template */ |
3066 | ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */ | 3086 | ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */ |
3087 | QUE_XRI64_CX_FIELDS quexri64cx; /* que_xri64_cx fields */ | ||
3067 | 3088 | ||
3068 | uint32_t ulpWord[IOCB_WORD_SZ - 2]; /* generic 6 'words' */ | 3089 | uint32_t ulpWord[IOCB_WORD_SZ - 2]; /* generic 6 'words' */ |
3069 | } un; | 3090 | } un; |
@@ -3121,6 +3142,10 @@ typedef struct _IOCB { /* IOCB structure */ | |||
3121 | 3142 | ||
3122 | union { | 3143 | union { |
3123 | struct rcv_sli3 rcvsli3; /* words 8 - 15 */ | 3144 | struct rcv_sli3 rcvsli3; /* words 8 - 15 */ |
3145 | |||
3146 | /* words 8-31 used for que_xri_cx iocb */ | ||
3147 | struct que_xri64cx_ext_fields que_xri64cx_ext_words; | ||
3148 | |||
3124 | uint32_t sli3Words[24]; /* 96 extra bytes for SLI-3 */ | 3149 | uint32_t sli3Words[24]; /* 96 extra bytes for SLI-3 */ |
3125 | } unsli3; | 3150 | } unsli3; |
3126 | 3151 | ||
@@ -3160,12 +3185,6 @@ typedef struct _IOCB { /* IOCB structure */ | |||
3160 | 3185 | ||
3161 | } IOCB_t; | 3186 | } IOCB_t; |
3162 | 3187 | ||
3163 | /* Structure used for a single HBQ entry */ | ||
3164 | struct lpfc_hbq_entry { | ||
3165 | struct ulp_bde64 bde; | ||
3166 | uint32_t buffer_tag; | ||
3167 | }; | ||
3168 | |||
3169 | 3188 | ||
3170 | #define SLI1_SLIM_SIZE (4 * 1024) | 3189 | #define SLI1_SLIM_SIZE (4 * 1024) |
3171 | 3190 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index c3743d6f445b..9bc85d5a02f7 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -931,6 +931,16 @@ lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag) | |||
931 | return &new_hbq_entry->dbuf; | 931 | return &new_hbq_entry->dbuf; |
932 | } | 932 | } |
933 | 933 | ||
934 | static struct lpfc_dmabuf * | ||
935 | lpfc_sli_get_buff(struct lpfc_hba *phba, | ||
936 | struct lpfc_sli_ring *pring, | ||
937 | uint32_t tag) | ||
938 | { | ||
939 | if (tag & QUE_BUFTAG_BIT) | ||
940 | return lpfc_sli_ring_taggedbuf_get(phba, pring, tag); | ||
941 | else | ||
942 | return lpfc_sli_replace_hbqbuff(phba, tag); | ||
943 | } | ||
934 | 944 | ||
935 | static int | 945 | static int |
936 | lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 946 | lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
@@ -940,6 +950,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
940 | WORD5 * w5p; | 950 | WORD5 * w5p; |
941 | uint32_t Rctl, Type; | 951 | uint32_t Rctl, Type; |
942 | uint32_t match, i; | 952 | uint32_t match, i; |
953 | struct lpfc_iocbq *iocbq; | ||
943 | 954 | ||
944 | match = 0; | 955 | match = 0; |
945 | irsp = &(saveq->iocb); | 956 | irsp = &(saveq->iocb); |
@@ -984,12 +995,69 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
984 | } | 995 | } |
985 | 996 | ||
986 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { | 997 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { |
987 | if (irsp->ulpBdeCount != 0) | 998 | struct lpfc_hbq_entry *hbqe_1, *hbqe_2; |
988 | saveq->context2 = lpfc_sli_replace_hbqbuff(phba, | 999 | hbqe_1 = (struct lpfc_hbq_entry *) &saveq->iocb.un.ulpWord[0]; |
1000 | hbqe_2 = (struct lpfc_hbq_entry *) &saveq->iocb. | ||
1001 | unsli3.sli3Words[4]; | ||
1002 | |||
1003 | if (irsp->ulpBdeCount != 0) { | ||
1004 | saveq->context2 = lpfc_sli_get_buff(phba, pring, | ||
989 | irsp->un.ulpWord[3]); | 1005 | irsp->un.ulpWord[3]); |
990 | if (irsp->ulpBdeCount == 2) | 1006 | if (!saveq->context2) |
991 | saveq->context3 = lpfc_sli_replace_hbqbuff(phba, | 1007 | lpfc_printf_log(phba, |
1008 | KERN_ERR, | ||
1009 | LOG_SLI, | ||
1010 | "0341 Ring %d Cannot find buffer for " | ||
1011 | "an unsolicited iocb. tag 0x%x\n", | ||
1012 | pring->ringno, | ||
1013 | irsp->un.ulpWord[3]); | ||
1014 | |||
1015 | } | ||
1016 | if (irsp->ulpBdeCount == 2) { | ||
1017 | saveq->context3 = lpfc_sli_get_buff(phba, pring, | ||
992 | irsp->unsli3.sli3Words[7]); | 1018 | irsp->unsli3.sli3Words[7]); |
1019 | if (!saveq->context3) | ||
1020 | lpfc_printf_log(phba, | ||
1021 | KERN_ERR, | ||
1022 | LOG_SLI, | ||
1023 | "0342 Ring %d Cannot find buffer for an" | ||
1024 | " unsolicited iocb. tag 0x%x\n", | ||
1025 | pring->ringno, | ||
1026 | irsp->unsli3.sli3Words[7]); | ||
1027 | } | ||
1028 | list_for_each_entry(iocbq, &saveq->list, list) { | ||
1029 | hbqe_1 = (struct lpfc_hbq_entry *) &iocbq->iocb. | ||
1030 | un.ulpWord[0]; | ||
1031 | hbqe_2 = (struct lpfc_hbq_entry *) &iocbq->iocb. | ||
1032 | unsli3.sli3Words[4]; | ||
1033 | irsp = &(iocbq->iocb); | ||
1034 | |||
1035 | if (irsp->ulpBdeCount != 0) { | ||
1036 | iocbq->context2 = lpfc_sli_get_buff(phba, pring, | ||
1037 | irsp->un.ulpWord[3]); | ||
1038 | if (!saveq->context2) | ||
1039 | lpfc_printf_log(phba, | ||
1040 | KERN_ERR, | ||
1041 | LOG_SLI, | ||
1042 | "0343 Ring %d Cannot find " | ||
1043 | "buffer for an unsolicited iocb" | ||
1044 | ". tag 0x%x\n", pring->ringno, | ||
1045 | irsp->un.ulpWord[3]); | ||
1046 | } | ||
1047 | if (irsp->ulpBdeCount == 2) { | ||
1048 | iocbq->context3 = lpfc_sli_get_buff(phba, pring, | ||
1049 | irsp->unsli3.sli3Words[7]); | ||
1050 | if (!saveq->context3) | ||
1051 | lpfc_printf_log(phba, | ||
1052 | KERN_ERR, | ||
1053 | LOG_SLI, | ||
1054 | "0344 Ring %d Cannot find " | ||
1055 | "buffer for an unsolicited " | ||
1056 | "iocb. tag 0x%x\n", | ||
1057 | pring->ringno, | ||
1058 | irsp->unsli3.sli3Words[7]); | ||
1059 | } | ||
1060 | } | ||
993 | } | 1061 | } |
994 | 1062 | ||
995 | /* unSolicited Responses */ | 1063 | /* unSolicited Responses */ |
@@ -2480,7 +2548,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) | |||
2480 | lpfc_sli_abort_iocb_ring(phba, pring); | 2548 | lpfc_sli_abort_iocb_ring(phba, pring); |
2481 | 2549 | ||
2482 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | 2550 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, |
2483 | "0316 Resetting board due to mailbox timeout\n"); | 2551 | "0345 Resetting board due to mailbox timeout\n"); |
2484 | /* | 2552 | /* |
2485 | * lpfc_offline calls lpfc_sli_hba_down which will clean up | 2553 | * lpfc_offline calls lpfc_sli_hba_down which will clean up |
2486 | * on oustanding mailbox commands. | 2554 | * on oustanding mailbox commands. |
@@ -2975,7 +3043,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, | |||
2975 | lpfc_printf_log(phba, | 3043 | lpfc_printf_log(phba, |
2976 | KERN_ERR, | 3044 | KERN_ERR, |
2977 | LOG_SLI, | 3045 | LOG_SLI, |
2978 | "0327 Ring %d handler: unexpected ASYNC_STATUS" | 3046 | "0346 Ring %d handler: unexpected ASYNC_STATUS" |
2979 | " evt_code 0x%x\n", | 3047 | " evt_code 0x%x\n", |
2980 | pring->ringno, | 3048 | pring->ringno, |
2981 | icmd->un.asyncstat.evt_code); | 3049 | icmd->un.asyncstat.evt_code); |
@@ -2988,7 +3056,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, | |||
2988 | lpfc_printf_log(phba, | 3056 | lpfc_printf_log(phba, |
2989 | KERN_WARNING, | 3057 | KERN_WARNING, |
2990 | LOG_TEMP, | 3058 | LOG_TEMP, |
2991 | "0339 Adapter is very hot, please take " | 3059 | "0347 Adapter is very hot, please take " |
2992 | "corrective action. temperature : %d Celsius\n", | 3060 | "corrective action. temperature : %d Celsius\n", |
2993 | temp); | 3061 | temp); |
2994 | } | 3062 | } |
@@ -3314,6 +3382,47 @@ lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3314 | return 0; | 3382 | return 0; |
3315 | } | 3383 | } |
3316 | 3384 | ||
3385 | uint32_t | ||
3386 | lpfc_sli_get_buffer_tag(struct lpfc_hba *phba) | ||
3387 | { | ||
3388 | spin_lock_irq(&phba->hbalock); | ||
3389 | phba->buffer_tag_count++; | ||
3390 | /* | ||
3391 | * Always set the QUE_BUFTAG_BIT to distiguish between | ||
3392 | * a tag assigned by HBQ. | ||
3393 | */ | ||
3394 | phba->buffer_tag_count |= QUE_BUFTAG_BIT; | ||
3395 | spin_unlock_irq(&phba->hbalock); | ||
3396 | return phba->buffer_tag_count; | ||
3397 | } | ||
3398 | |||
3399 | struct lpfc_dmabuf * | ||
3400 | lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | ||
3401 | uint32_t tag) | ||
3402 | { | ||
3403 | struct lpfc_dmabuf *mp, *next_mp; | ||
3404 | struct list_head *slp = &pring->postbufq; | ||
3405 | |||
3406 | /* Search postbufq, from the begining, looking for a match on tag */ | ||
3407 | spin_lock_irq(&phba->hbalock); | ||
3408 | list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) { | ||
3409 | if (mp->buffer_tag == tag) { | ||
3410 | list_del_init(&mp->list); | ||
3411 | pring->postbufq_cnt--; | ||
3412 | spin_unlock_irq(&phba->hbalock); | ||
3413 | return mp; | ||
3414 | } | ||
3415 | } | ||
3416 | |||
3417 | spin_unlock_irq(&phba->hbalock); | ||
3418 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
3419 | "0410 Cannot find virtual addr for buffer tag on " | ||
3420 | "ring %d Data x%lx x%p x%p x%x\n", | ||
3421 | pring->ringno, (unsigned long) tag, | ||
3422 | slp->next, slp->prev, pring->postbufq_cnt); | ||
3423 | |||
3424 | return NULL; | ||
3425 | } | ||
3317 | 3426 | ||
3318 | struct lpfc_dmabuf * | 3427 | struct lpfc_dmabuf * |
3319 | lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 3428 | lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |