aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_nportdisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_nportdisc.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c93
1 files changed, 54 insertions, 39 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 3e74136f1ede..e331204a4d56 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -21,6 +21,7 @@
21 21
22#include <linux/blkdev.h> 22#include <linux/blkdev.h>
23#include <linux/pci.h> 23#include <linux/pci.h>
24#include <linux/slab.h>
24#include <linux/interrupt.h> 25#include <linux/interrupt.h>
25 26
26#include <scsi/scsi.h> 27#include <scsi/scsi.h>
@@ -62,7 +63,7 @@ lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
62 63
63int 64int
64lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, 65lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
65 struct serv_parm * sp, uint32_t class) 66 struct serv_parm *sp, uint32_t class, int flogi)
66{ 67{
67 volatile struct serv_parm *hsp = &vport->fc_sparam; 68 volatile struct serv_parm *hsp = &vport->fc_sparam;
68 uint16_t hsp_value, ssp_value = 0; 69 uint16_t hsp_value, ssp_value = 0;
@@ -75,49 +76,56 @@ lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
75 * correcting the byte values. 76 * correcting the byte values.
76 */ 77 */
77 if (sp->cls1.classValid) { 78 if (sp->cls1.classValid) {
78 hsp_value = (hsp->cls1.rcvDataSizeMsb << 8) | 79 if (!flogi) {
79 hsp->cls1.rcvDataSizeLsb; 80 hsp_value = ((hsp->cls1.rcvDataSizeMsb << 8) |
80 ssp_value = (sp->cls1.rcvDataSizeMsb << 8) | 81 hsp->cls1.rcvDataSizeLsb);
81 sp->cls1.rcvDataSizeLsb; 82 ssp_value = ((sp->cls1.rcvDataSizeMsb << 8) |
82 if (!ssp_value) 83 sp->cls1.rcvDataSizeLsb);
83 goto bad_service_param; 84 if (!ssp_value)
84 if (ssp_value > hsp_value) { 85 goto bad_service_param;
85 sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb; 86 if (ssp_value > hsp_value) {
86 sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb; 87 sp->cls1.rcvDataSizeLsb =
88 hsp->cls1.rcvDataSizeLsb;
89 sp->cls1.rcvDataSizeMsb =
90 hsp->cls1.rcvDataSizeMsb;
91 }
87 } 92 }
88 } else if (class == CLASS1) { 93 } else if (class == CLASS1)
89 goto bad_service_param; 94 goto bad_service_param;
90 }
91
92 if (sp->cls2.classValid) { 95 if (sp->cls2.classValid) {
93 hsp_value = (hsp->cls2.rcvDataSizeMsb << 8) | 96 if (!flogi) {
94 hsp->cls2.rcvDataSizeLsb; 97 hsp_value = ((hsp->cls2.rcvDataSizeMsb << 8) |
95 ssp_value = (sp->cls2.rcvDataSizeMsb << 8) | 98 hsp->cls2.rcvDataSizeLsb);
96 sp->cls2.rcvDataSizeLsb; 99 ssp_value = ((sp->cls2.rcvDataSizeMsb << 8) |
97 if (!ssp_value) 100 sp->cls2.rcvDataSizeLsb);
98 goto bad_service_param; 101 if (!ssp_value)
99 if (ssp_value > hsp_value) { 102 goto bad_service_param;
100 sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb; 103 if (ssp_value > hsp_value) {
101 sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb; 104 sp->cls2.rcvDataSizeLsb =
105 hsp->cls2.rcvDataSizeLsb;
106 sp->cls2.rcvDataSizeMsb =
107 hsp->cls2.rcvDataSizeMsb;
108 }
102 } 109 }
103 } else if (class == CLASS2) { 110 } else if (class == CLASS2)
104 goto bad_service_param; 111 goto bad_service_param;
105 }
106
107 if (sp->cls3.classValid) { 112 if (sp->cls3.classValid) {
108 hsp_value = (hsp->cls3.rcvDataSizeMsb << 8) | 113 if (!flogi) {
109 hsp->cls3.rcvDataSizeLsb; 114 hsp_value = ((hsp->cls3.rcvDataSizeMsb << 8) |
110 ssp_value = (sp->cls3.rcvDataSizeMsb << 8) | 115 hsp->cls3.rcvDataSizeLsb);
111 sp->cls3.rcvDataSizeLsb; 116 ssp_value = ((sp->cls3.rcvDataSizeMsb << 8) |
112 if (!ssp_value) 117 sp->cls3.rcvDataSizeLsb);
113 goto bad_service_param; 118 if (!ssp_value)
114 if (ssp_value > hsp_value) { 119 goto bad_service_param;
115 sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb; 120 if (ssp_value > hsp_value) {
116 sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb; 121 sp->cls3.rcvDataSizeLsb =
122 hsp->cls3.rcvDataSizeLsb;
123 sp->cls3.rcvDataSizeMsb =
124 hsp->cls3.rcvDataSizeMsb;
125 }
117 } 126 }
118 } else if (class == CLASS3) { 127 } else if (class == CLASS3)
119 goto bad_service_param; 128 goto bad_service_param;
120 }
121 129
122 /* 130 /*
123 * Preserve the upper four bits of the MSB from the PLOGI response. 131 * Preserve the upper four bits of the MSB from the PLOGI response.
@@ -247,7 +255,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
247 int rc; 255 int rc;
248 256
249 memset(&stat, 0, sizeof (struct ls_rjt)); 257 memset(&stat, 0, sizeof (struct ls_rjt));
250 if (vport->port_state <= LPFC_FLOGI) { 258 if (vport->port_state <= LPFC_FDISC) {
251 /* Before responding to PLOGI, check for pt2pt mode. 259 /* Before responding to PLOGI, check for pt2pt mode.
252 * If we are pt2pt, with an outstanding FLOGI, abort 260 * If we are pt2pt, with an outstanding FLOGI, abort
253 * the FLOGI and resend it first. 261 * the FLOGI and resend it first.
@@ -295,7 +303,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
295 NULL); 303 NULL);
296 return 0; 304 return 0;
297 } 305 }
298 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) { 306 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0) == 0)) {
299 /* Reject this request because invalid parameters */ 307 /* Reject this request because invalid parameters */
300 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; 308 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
301 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; 309 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
@@ -831,7 +839,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
831 "0142 PLOGI RSP: Invalid WWN.\n"); 839 "0142 PLOGI RSP: Invalid WWN.\n");
832 goto out; 840 goto out;
833 } 841 }
834 if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3)) 842 if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0))
835 goto out; 843 goto out;
836 /* PLOGI chkparm OK */ 844 /* PLOGI chkparm OK */
837 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, 845 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
@@ -1223,6 +1231,12 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
1223 list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { 1231 list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
1224 if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && 1232 if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) &&
1225 (ndlp == (struct lpfc_nodelist *) mb->context2)) { 1233 (ndlp == (struct lpfc_nodelist *) mb->context2)) {
1234 if (phba->sli_rev == LPFC_SLI_REV4) {
1235 spin_unlock_irq(&phba->hbalock);
1236 lpfc_sli4_free_rpi(phba,
1237 mb->u.mb.un.varRegLogin.rpi);
1238 spin_lock_irq(&phba->hbalock);
1239 }
1226 mp = (struct lpfc_dmabuf *) (mb->context1); 1240 mp = (struct lpfc_dmabuf *) (mb->context1);
1227 if (mp) { 1241 if (mp) {
1228 __lpfc_mbuf_free(phba, mp->virt, mp->phys); 1242 __lpfc_mbuf_free(phba, mp->virt, mp->phys);
@@ -1230,6 +1244,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
1230 } 1244 }
1231 lpfc_nlp_put(ndlp); 1245 lpfc_nlp_put(ndlp);
1232 list_del(&mb->list); 1246 list_del(&mb->list);
1247 phba->sli.mboxq_cnt--;
1233 mempool_free(mb, phba->mbox_mem_pool); 1248 mempool_free(mb, phba->mbox_mem_pool);
1234 } 1249 }
1235 } 1250 }