diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_nportdisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 93 |
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 | ||
63 | int | 64 | int |
64 | lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 65 | lpfc_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 | } |