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, |
