aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-10-27 13:38:00 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-11 19:22:33 -0500
commit76bb24efdc5de8eead0ccc07ec7e3b59a4ca0f15 (patch)
tree989311bb1be4a8331407bb6d3d67e5bd95e8a7a6 /drivers/scsi/lpfc
parenta8adb83208020c913f010cb4e26d09e25300db8e (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>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc.h7
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h31
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c123
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
73struct lpfc_dma_pool { 74struct 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
587static inline struct Scsi_Host * 594static 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 *,
211struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, 211struct 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
215uint32_t lpfc_sli_get_buffer_tag(struct lpfc_hba *);
216struct lpfc_dmabuf * lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *,
217 struct lpfc_sli_ring *, uint32_t );
218
214int lpfc_sli_hbq_count(void); 219int lpfc_sli_hbq_count(void);
215int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t); 220int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t);
216int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t); 221int 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 */
3044struct 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 */
3050typedef struct {
3051 struct lpfc_hbq_entry buff;
3052 uint32_t rsvd;
3053 uint32_t rsvd1;
3054} QUE_XRI64_CX_FIELDS;
3055
3056struct 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
3044typedef struct _IOCB { /* IOCB structure */ 3064typedef 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 */
3164struct 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
934static struct lpfc_dmabuf *
935lpfc_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
935static int 945static int
936lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, 946lpfc_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
3385uint32_t
3386lpfc_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
3399struct lpfc_dmabuf *
3400lpfc_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
3318struct lpfc_dmabuf * 3427struct lpfc_dmabuf *
3319lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, 3428lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,