aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c69
1 files changed, 45 insertions, 24 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 507a6af56f42..fbead786031f 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -55,55 +55,76 @@ lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
55 return (1); 55 return (1);
56} 56}
57 57
58
59int 58int
60lpfc_check_sparm(struct lpfc_hba * phba, 59lpfc_check_sparm(struct lpfc_hba * phba,
61 struct lpfc_nodelist * ndlp, struct serv_parm * sp, 60 struct lpfc_nodelist * ndlp, struct serv_parm * sp,
62 uint32_t class) 61 uint32_t class)
63{ 62{
64 volatile struct serv_parm *hsp = &phba->fc_sparam; 63 volatile struct serv_parm *hsp = &phba->fc_sparam;
65 /* First check for supported version */ 64 uint16_t hsp_value, ssp_value = 0;
66 65
67 /* Next check for class validity */ 66 /*
67 * The receive data field size and buffer-to-buffer receive data field
68 * size entries are 16 bits but are represented as two 8-bit fields in
69 * the driver data structure to account for rsvd bits and other control
70 * bits. Reconstruct and compare the fields as a 16-bit values before
71 * correcting the byte values.
72 */
68 if (sp->cls1.classValid) { 73 if (sp->cls1.classValid) {
69 74 hsp_value = (hsp->cls1.rcvDataSizeMsb << 8) |
70 if (sp->cls1.rcvDataSizeMsb > hsp->cls1.rcvDataSizeMsb) 75 hsp->cls1.rcvDataSizeLsb;
71 sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb; 76 ssp_value = (sp->cls1.rcvDataSizeMsb << 8) |
72 if (sp->cls1.rcvDataSizeLsb > hsp->cls1.rcvDataSizeLsb) 77 sp->cls1.rcvDataSizeLsb;
78 if (ssp_value > hsp_value) {
73 sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb; 79 sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb;
80 sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
81 }
74 } else if (class == CLASS1) { 82 } else if (class == CLASS1) {
75 return (0); 83 return 0;
76 } 84 }
77 85
78 if (sp->cls2.classValid) { 86 if (sp->cls2.classValid) {
79 87 hsp_value = (hsp->cls2.rcvDataSizeMsb << 8) |
80 if (sp->cls2.rcvDataSizeMsb > hsp->cls2.rcvDataSizeMsb) 88 hsp->cls2.rcvDataSizeLsb;
81 sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb; 89 ssp_value = (sp->cls2.rcvDataSizeMsb << 8) |
82 if (sp->cls2.rcvDataSizeLsb > hsp->cls2.rcvDataSizeLsb) 90 sp->cls2.rcvDataSizeLsb;
91 if (ssp_value > hsp_value) {
83 sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb; 92 sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb;
93 sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
94 }
84 } else if (class == CLASS2) { 95 } else if (class == CLASS2) {
85 return (0); 96 return 0;
86 } 97 }
87 98
88 if (sp->cls3.classValid) { 99 if (sp->cls3.classValid) {
89 100 hsp_value = (hsp->cls3.rcvDataSizeMsb << 8) |
90 if (sp->cls3.rcvDataSizeMsb > hsp->cls3.rcvDataSizeMsb) 101 hsp->cls3.rcvDataSizeLsb;
91 sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb; 102 ssp_value = (sp->cls3.rcvDataSizeMsb << 8) |
92 if (sp->cls3.rcvDataSizeLsb > hsp->cls3.rcvDataSizeLsb) 103 sp->cls3.rcvDataSizeLsb;
104 if (ssp_value > hsp_value) {
93 sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb; 105 sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb;
106 sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
107 }
94 } else if (class == CLASS3) { 108 } else if (class == CLASS3) {
95 return (0); 109 return 0;
96 } 110 }
97 111
98 if (sp->cmn.bbRcvSizeMsb > hsp->cmn.bbRcvSizeMsb) 112 /*
99 sp->cmn.bbRcvSizeMsb = hsp->cmn.bbRcvSizeMsb; 113 * Preserve the upper four bits of the MSB from the PLOGI response.
100 if (sp->cmn.bbRcvSizeLsb > hsp->cmn.bbRcvSizeLsb) 114 * These bits contain the Buffer-to-Buffer State Change Number
115 * from the target and need to be passed to the FW.
116 */
117 hsp_value = (hsp->cmn.bbRcvSizeMsb << 8) | hsp->cmn.bbRcvSizeLsb;
118 ssp_value = (sp->cmn.bbRcvSizeMsb << 8) | sp->cmn.bbRcvSizeLsb;
119 if (ssp_value > hsp_value) {
101 sp->cmn.bbRcvSizeLsb = hsp->cmn.bbRcvSizeLsb; 120 sp->cmn.bbRcvSizeLsb = hsp->cmn.bbRcvSizeLsb;
121 sp->cmn.bbRcvSizeMsb = (sp->cmn.bbRcvSizeMsb & 0xF0) |
122 (hsp->cmn.bbRcvSizeMsb & 0x0F);
123 }
102 124
103 /* If check is good, copy wwpn wwnn into ndlp */
104 memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name)); 125 memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
105 memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name)); 126 memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));
106 return (1); 127 return 1;
107} 128}
108 129
109static void * 130static void *