diff options
Diffstat (limited to 'drivers/scsi/fnic')
-rw-r--r-- | drivers/scsi/fnic/fnic.h | 23 | ||||
-rw-r--r-- | drivers/scsi/fnic/fnic_fcs.c | 499 | ||||
-rw-r--r-- | drivers/scsi/fnic/fnic_main.c | 71 | ||||
-rw-r--r-- | drivers/scsi/fnic/fnic_res.c | 5 | ||||
-rw-r--r-- | drivers/scsi/fnic/fnic_res.h | 50 | ||||
-rw-r--r-- | drivers/scsi/fnic/fnic_scsi.c | 73 | ||||
-rw-r--r-- | drivers/scsi/fnic/vnic_scsi.h | 1 |
7 files changed, 381 insertions, 341 deletions
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 1bc267e892d2..bb208a6091e7 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/netdevice.h> | 22 | #include <linux/netdevice.h> |
23 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
24 | #include <scsi/libfc.h> | 24 | #include <scsi/libfc.h> |
25 | #include <scsi/libfcoe.h> | ||
25 | #include "fnic_io.h" | 26 | #include "fnic_io.h" |
26 | #include "fnic_res.h" | 27 | #include "fnic_res.h" |
27 | #include "vnic_dev.h" | 28 | #include "vnic_dev.h" |
@@ -145,6 +146,7 @@ struct mempool; | |||
145 | /* Per-instance private data structure */ | 146 | /* Per-instance private data structure */ |
146 | struct fnic { | 147 | struct fnic { |
147 | struct fc_lport *lport; | 148 | struct fc_lport *lport; |
149 | struct fcoe_ctlr ctlr; /* FIP FCoE controller structure */ | ||
148 | struct vnic_dev_bar bar0; | 150 | struct vnic_dev_bar bar0; |
149 | 151 | ||
150 | struct msix_entry msix_entry[FNIC_MSIX_INTR_MAX]; | 152 | struct msix_entry msix_entry[FNIC_MSIX_INTR_MAX]; |
@@ -162,23 +164,16 @@ struct fnic { | |||
162 | unsigned int wq_count; | 164 | unsigned int wq_count; |
163 | unsigned int cq_count; | 165 | unsigned int cq_count; |
164 | 166 | ||
165 | u32 fcoui_mode:1; /* use fcoui address*/ | ||
166 | u32 vlan_hw_insert:1; /* let hw insert the tag */ | 167 | u32 vlan_hw_insert:1; /* let hw insert the tag */ |
167 | u32 in_remove:1; /* fnic device in removal */ | 168 | u32 in_remove:1; /* fnic device in removal */ |
168 | u32 stop_rx_link_events:1; /* stop proc. rx frames, link events */ | 169 | u32 stop_rx_link_events:1; /* stop proc. rx frames, link events */ |
169 | 170 | ||
170 | struct completion *remove_wait; /* device remove thread blocks */ | 171 | struct completion *remove_wait; /* device remove thread blocks */ |
171 | 172 | ||
172 | struct fc_frame *flogi; | ||
173 | struct fc_frame *flogi_resp; | ||
174 | u16 flogi_oxid; | ||
175 | unsigned long s_id; | ||
176 | enum fnic_state state; | 173 | enum fnic_state state; |
177 | spinlock_t fnic_lock; | 174 | spinlock_t fnic_lock; |
178 | 175 | ||
179 | u16 vlan_id; /* VLAN tag including priority */ | 176 | u16 vlan_id; /* VLAN tag including priority */ |
180 | u8 mac_addr[ETH_ALEN]; | ||
181 | u8 dest_addr[ETH_ALEN]; | ||
182 | u8 data_src_addr[ETH_ALEN]; | 177 | u8 data_src_addr[ETH_ALEN]; |
183 | u64 fcp_input_bytes; /* internal statistic */ | 178 | u64 fcp_input_bytes; /* internal statistic */ |
184 | u64 fcp_output_bytes; /* internal statistic */ | 179 | u64 fcp_output_bytes; /* internal statistic */ |
@@ -205,6 +200,7 @@ struct fnic { | |||
205 | struct work_struct link_work; | 200 | struct work_struct link_work; |
206 | struct work_struct frame_work; | 201 | struct work_struct frame_work; |
207 | struct sk_buff_head frame_queue; | 202 | struct sk_buff_head frame_queue; |
203 | struct sk_buff_head tx_queue; | ||
208 | 204 | ||
209 | /* copy work queue cache line section */ | 205 | /* copy work queue cache line section */ |
210 | ____cacheline_aligned struct vnic_wq_copy wq_copy[FNIC_WQ_COPY_MAX]; | 206 | ____cacheline_aligned struct vnic_wq_copy wq_copy[FNIC_WQ_COPY_MAX]; |
@@ -224,6 +220,11 @@ struct fnic { | |||
224 | ____cacheline_aligned struct vnic_intr intr[FNIC_MSIX_INTR_MAX]; | 220 | ____cacheline_aligned struct vnic_intr intr[FNIC_MSIX_INTR_MAX]; |
225 | }; | 221 | }; |
226 | 222 | ||
223 | static inline struct fnic *fnic_from_ctlr(struct fcoe_ctlr *fip) | ||
224 | { | ||
225 | return container_of(fip, struct fnic, ctlr); | ||
226 | } | ||
227 | |||
227 | extern struct workqueue_struct *fnic_event_queue; | 228 | extern struct workqueue_struct *fnic_event_queue; |
228 | extern struct device_attribute *fnic_attrs[]; | 229 | extern struct device_attribute *fnic_attrs[]; |
229 | 230 | ||
@@ -239,7 +240,11 @@ void fnic_handle_link(struct work_struct *work); | |||
239 | int fnic_rq_cmpl_handler(struct fnic *fnic, int); | 240 | int fnic_rq_cmpl_handler(struct fnic *fnic, int); |
240 | int fnic_alloc_rq_frame(struct vnic_rq *rq); | 241 | int fnic_alloc_rq_frame(struct vnic_rq *rq); |
241 | void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf); | 242 | void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf); |
242 | int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp); | 243 | void fnic_flush_tx(struct fnic *); |
244 | void fnic_eth_send(struct fcoe_ctlr *, struct sk_buff *skb); | ||
245 | void fnic_set_port_id(struct fc_lport *, u32, struct fc_frame *); | ||
246 | void fnic_update_mac(struct fc_lport *, u8 *new); | ||
247 | void fnic_update_mac_locked(struct fnic *, u8 *new); | ||
243 | 248 | ||
244 | int fnic_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); | 249 | int fnic_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); |
245 | int fnic_abort_cmd(struct scsi_cmnd *); | 250 | int fnic_abort_cmd(struct scsi_cmnd *); |
@@ -252,7 +257,7 @@ void fnic_empty_scsi_cleanup(struct fc_lport *); | |||
252 | void fnic_exch_mgr_reset(struct fc_lport *, u32, u32); | 257 | void fnic_exch_mgr_reset(struct fc_lport *, u32, u32); |
253 | int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int); | 258 | int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int); |
254 | int fnic_wq_cmpl_handler(struct fnic *fnic, int); | 259 | int fnic_wq_cmpl_handler(struct fnic *fnic, int); |
255 | int fnic_flogi_reg_handler(struct fnic *fnic); | 260 | int fnic_flogi_reg_handler(struct fnic *fnic, u32); |
256 | void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq, | 261 | void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq, |
257 | struct fcpio_host_req *desc); | 262 | struct fcpio_host_req *desc); |
258 | int fnic_fw_reset_handler(struct fnic *fnic); | 263 | int fnic_fw_reset_handler(struct fnic *fnic); |
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index 50db3e36a619..54f8d0e5407f 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/if_ether.h> | 23 | #include <linux/if_ether.h> |
24 | #include <linux/if_vlan.h> | 24 | #include <linux/if_vlan.h> |
25 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
26 | #include <scsi/fc/fc_fip.h> | ||
26 | #include <scsi/fc/fc_els.h> | 27 | #include <scsi/fc/fc_els.h> |
27 | #include <scsi/fc/fc_fcoe.h> | 28 | #include <scsi/fc/fc_fcoe.h> |
28 | #include <scsi/fc_frame.h> | 29 | #include <scsi/fc_frame.h> |
@@ -34,6 +35,8 @@ | |||
34 | 35 | ||
35 | struct workqueue_struct *fnic_event_queue; | 36 | struct workqueue_struct *fnic_event_queue; |
36 | 37 | ||
38 | static void fnic_set_eth_mode(struct fnic *); | ||
39 | |||
37 | void fnic_handle_link(struct work_struct *work) | 40 | void fnic_handle_link(struct work_struct *work) |
38 | { | 41 | { |
39 | struct fnic *fnic = container_of(work, struct fnic, link_work); | 42 | struct fnic *fnic = container_of(work, struct fnic, link_work); |
@@ -64,10 +67,10 @@ void fnic_handle_link(struct work_struct *work) | |||
64 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 67 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
65 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | 68 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, |
66 | "link down\n"); | 69 | "link down\n"); |
67 | fc_linkdown(fnic->lport); | 70 | fcoe_ctlr_link_down(&fnic->ctlr); |
68 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | 71 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, |
69 | "link up\n"); | 72 | "link up\n"); |
70 | fc_linkup(fnic->lport); | 73 | fcoe_ctlr_link_up(&fnic->ctlr); |
71 | } else | 74 | } else |
72 | /* UP -> UP */ | 75 | /* UP -> UP */ |
73 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 76 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
@@ -76,13 +79,13 @@ void fnic_handle_link(struct work_struct *work) | |||
76 | /* DOWN -> UP */ | 79 | /* DOWN -> UP */ |
77 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 80 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
78 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link up\n"); | 81 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link up\n"); |
79 | fc_linkup(fnic->lport); | 82 | fcoe_ctlr_link_up(&fnic->ctlr); |
80 | } else { | 83 | } else { |
81 | /* UP -> DOWN */ | 84 | /* UP -> DOWN */ |
82 | fnic->lport->host_stats.link_failure_count++; | 85 | fnic->lport->host_stats.link_failure_count++; |
83 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 86 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
84 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link down\n"); | 87 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link down\n"); |
85 | fc_linkdown(fnic->lport); | 88 | fcoe_ctlr_link_down(&fnic->ctlr); |
86 | } | 89 | } |
87 | 90 | ||
88 | } | 91 | } |
@@ -107,197 +110,179 @@ void fnic_handle_frame(struct work_struct *work) | |||
107 | return; | 110 | return; |
108 | } | 111 | } |
109 | fp = (struct fc_frame *)skb; | 112 | fp = (struct fc_frame *)skb; |
110 | /* if Flogi resp frame, register the address */ | 113 | |
111 | if (fr_flags(fp)) { | 114 | /* |
112 | vnic_dev_add_addr(fnic->vdev, | 115 | * If we're in a transitional state, just re-queue and return. |
113 | fnic->data_src_addr); | 116 | * The queue will be serviced when we get to a stable state. |
114 | fr_flags(fp) = 0; | 117 | */ |
118 | if (fnic->state != FNIC_IN_FC_MODE && | ||
119 | fnic->state != FNIC_IN_ETH_MODE) { | ||
120 | skb_queue_head(&fnic->frame_queue, skb); | ||
121 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
122 | return; | ||
115 | } | 123 | } |
116 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 124 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
117 | 125 | ||
118 | fc_exch_recv(lp, fp); | 126 | fc_exch_recv(lp, fp); |
119 | } | 127 | } |
120 | |||
121 | } | ||
122 | |||
123 | static inline void fnic_import_rq_fc_frame(struct sk_buff *skb, | ||
124 | u32 len, u8 sof, u8 eof) | ||
125 | { | ||
126 | struct fc_frame *fp = (struct fc_frame *)skb; | ||
127 | |||
128 | skb_trim(skb, len); | ||
129 | fr_eof(fp) = eof; | ||
130 | fr_sof(fp) = sof; | ||
131 | } | 128 | } |
132 | 129 | ||
133 | 130 | /** | |
134 | static inline int fnic_import_rq_eth_pkt(struct sk_buff *skb, u32 len) | 131 | * fnic_import_rq_eth_pkt() - handle received FCoE or FIP frame. |
132 | * @fnic: fnic instance. | ||
133 | * @skb: Ethernet Frame. | ||
134 | */ | ||
135 | static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, struct sk_buff *skb) | ||
135 | { | 136 | { |
136 | struct fc_frame *fp; | 137 | struct fc_frame *fp; |
137 | struct ethhdr *eh; | 138 | struct ethhdr *eh; |
138 | struct vlan_ethhdr *vh; | ||
139 | struct fcoe_hdr *fcoe_hdr; | 139 | struct fcoe_hdr *fcoe_hdr; |
140 | struct fcoe_crc_eof *ft; | 140 | struct fcoe_crc_eof *ft; |
141 | u32 transport_len = 0; | ||
142 | 141 | ||
142 | /* | ||
143 | * Undo VLAN encapsulation if present. | ||
144 | */ | ||
143 | eh = (struct ethhdr *)skb->data; | 145 | eh = (struct ethhdr *)skb->data; |
144 | vh = (struct vlan_ethhdr *)skb->data; | 146 | if (eh->h_proto == htons(ETH_P_8021Q)) { |
145 | if (vh->h_vlan_proto == htons(ETH_P_8021Q) && | 147 | memmove((u8 *)eh + VLAN_HLEN, eh, ETH_ALEN * 2); |
146 | vh->h_vlan_encapsulated_proto == htons(ETH_P_FCOE)) { | 148 | eh = (struct ethhdr *)skb_pull(skb, VLAN_HLEN); |
147 | skb_pull(skb, sizeof(struct vlan_ethhdr)); | 149 | skb_reset_mac_header(skb); |
148 | transport_len += sizeof(struct vlan_ethhdr); | 150 | } |
149 | } else if (eh->h_proto == htons(ETH_P_FCOE)) { | 151 | if (eh->h_proto == htons(ETH_P_FIP)) { |
150 | transport_len += sizeof(struct ethhdr); | 152 | skb_pull(skb, sizeof(*eh)); |
151 | skb_pull(skb, sizeof(struct ethhdr)); | 153 | fcoe_ctlr_recv(&fnic->ctlr, skb); |
152 | } else | 154 | return 1; /* let caller know packet was used */ |
153 | return -1; | 155 | } |
156 | if (eh->h_proto != htons(ETH_P_FCOE)) | ||
157 | goto drop; | ||
158 | skb_set_network_header(skb, sizeof(*eh)); | ||
159 | skb_pull(skb, sizeof(*eh)); | ||
154 | 160 | ||
155 | fcoe_hdr = (struct fcoe_hdr *)skb->data; | 161 | fcoe_hdr = (struct fcoe_hdr *)skb->data; |
156 | if (FC_FCOE_DECAPS_VER(fcoe_hdr) != FC_FCOE_VER) | 162 | if (FC_FCOE_DECAPS_VER(fcoe_hdr) != FC_FCOE_VER) |
157 | return -1; | 163 | goto drop; |
158 | 164 | ||
159 | fp = (struct fc_frame *)skb; | 165 | fp = (struct fc_frame *)skb; |
160 | fc_frame_init(fp); | 166 | fc_frame_init(fp); |
161 | fr_sof(fp) = fcoe_hdr->fcoe_sof; | 167 | fr_sof(fp) = fcoe_hdr->fcoe_sof; |
162 | skb_pull(skb, sizeof(struct fcoe_hdr)); | 168 | skb_pull(skb, sizeof(struct fcoe_hdr)); |
163 | transport_len += sizeof(struct fcoe_hdr); | 169 | skb_reset_transport_header(skb); |
164 | 170 | ||
165 | ft = (struct fcoe_crc_eof *)(skb->data + len - | 171 | ft = (struct fcoe_crc_eof *)(skb->data + skb->len - sizeof(*ft)); |
166 | transport_len - sizeof(*ft)); | ||
167 | fr_eof(fp) = ft->fcoe_eof; | 172 | fr_eof(fp) = ft->fcoe_eof; |
168 | skb_trim(skb, len - transport_len - sizeof(*ft)); | 173 | skb_trim(skb, skb->len - sizeof(*ft)); |
169 | return 0; | 174 | return 0; |
175 | drop: | ||
176 | dev_kfree_skb_irq(skb); | ||
177 | return -1; | ||
170 | } | 178 | } |
171 | 179 | ||
172 | static inline int fnic_handle_flogi_resp(struct fnic *fnic, | 180 | /** |
173 | struct fc_frame *fp) | 181 | * fnic_update_mac_locked() - set data MAC address and filters. |
182 | * @fnic: fnic instance. | ||
183 | * @new: newly-assigned FCoE MAC address. | ||
184 | * | ||
185 | * Called with the fnic lock held. | ||
186 | */ | ||
187 | void fnic_update_mac_locked(struct fnic *fnic, u8 *new) | ||
174 | { | 188 | { |
175 | u8 mac[ETH_ALEN] = FC_FCOE_FLOGI_MAC; | 189 | u8 *ctl = fnic->ctlr.ctl_src_addr; |
176 | struct ethhdr *eth_hdr; | 190 | u8 *data = fnic->data_src_addr; |
177 | struct fc_frame_header *fh; | ||
178 | int ret = 0; | ||
179 | unsigned long flags; | ||
180 | struct fc_frame *old_flogi_resp = NULL; | ||
181 | 191 | ||
182 | fh = (struct fc_frame_header *)fr_hdr(fp); | 192 | if (is_zero_ether_addr(new)) |
193 | new = ctl; | ||
194 | if (!compare_ether_addr(data, new)) | ||
195 | return; | ||
196 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "update_mac %pM\n", new); | ||
197 | if (!is_zero_ether_addr(data) && compare_ether_addr(data, ctl)) | ||
198 | vnic_dev_del_addr(fnic->vdev, data); | ||
199 | memcpy(data, new, ETH_ALEN); | ||
200 | if (compare_ether_addr(new, ctl)) | ||
201 | vnic_dev_add_addr(fnic->vdev, new); | ||
202 | } | ||
183 | 203 | ||
184 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 204 | /** |
205 | * fnic_update_mac() - set data MAC address and filters. | ||
206 | * @lport: local port. | ||
207 | * @new: newly-assigned FCoE MAC address. | ||
208 | */ | ||
209 | void fnic_update_mac(struct fc_lport *lport, u8 *new) | ||
210 | { | ||
211 | struct fnic *fnic = lport_priv(lport); | ||
185 | 212 | ||
186 | if (fnic->state == FNIC_IN_ETH_MODE) { | 213 | spin_lock_irq(&fnic->fnic_lock); |
214 | fnic_update_mac_locked(fnic, new); | ||
215 | spin_unlock_irq(&fnic->fnic_lock); | ||
216 | } | ||
187 | 217 | ||
188 | /* | 218 | /** |
189 | * Check if oxid matches on taking the lock. A new Flogi | 219 | * fnic_set_port_id() - set the port_ID after successful FLOGI. |
190 | * issued by libFC might have changed the fnic cached oxid | 220 | * @lport: local port. |
191 | */ | 221 | * @port_id: assigned FC_ID. |
192 | if (fnic->flogi_oxid != ntohs(fh->fh_ox_id)) { | 222 | * @fp: received frame containing the FLOGI accept or NULL. |
193 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | 223 | * |
194 | "Flogi response oxid not" | 224 | * This is called from libfc when a new FC_ID has been assigned. |
195 | " matching cached oxid, dropping frame" | 225 | * This causes us to reset the firmware to FC_MODE and setup the new MAC |
196 | "\n"); | 226 | * address and FC_ID. |
197 | ret = -1; | 227 | * |
198 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 228 | * It is also called with FC_ID 0 when we're logged off. |
199 | dev_kfree_skb_irq(fp_skb(fp)); | 229 | * |
200 | goto handle_flogi_resp_end; | 230 | * If the FC_ID is due to point-to-point, fp may be NULL. |
201 | } | 231 | */ |
232 | void fnic_set_port_id(struct fc_lport *lport, u32 port_id, struct fc_frame *fp) | ||
233 | { | ||
234 | struct fnic *fnic = lport_priv(lport); | ||
235 | u8 *mac; | ||
236 | int ret; | ||
202 | 237 | ||
203 | /* Drop older cached flogi response frame, cache this frame */ | 238 | FNIC_FCS_DBG(KERN_DEBUG, lport->host, "set port_id %x fp %p\n", |
204 | old_flogi_resp = fnic->flogi_resp; | 239 | port_id, fp); |
205 | fnic->flogi_resp = fp; | ||
206 | fnic->flogi_oxid = FC_XID_UNKNOWN; | ||
207 | 240 | ||
208 | /* | 241 | /* |
209 | * this frame is part of flogi get the src mac addr from this | 242 | * If we're clearing the FC_ID, change to use the ctl_src_addr. |
210 | * frame if the src mac is fcoui based then we mark the | 243 | * Set ethernet mode to send FLOGI. |
211 | * address mode flag to use fcoui base for dst mac addr | 244 | */ |
212 | * otherwise we have to store the fcoe gateway addr | 245 | if (!port_id) { |
213 | */ | 246 | fnic_update_mac(lport, fnic->ctlr.ctl_src_addr); |
214 | eth_hdr = (struct ethhdr *)skb_mac_header(fp_skb(fp)); | 247 | fnic_set_eth_mode(fnic); |
215 | memcpy(mac, eth_hdr->h_source, ETH_ALEN); | 248 | return; |
249 | } | ||
216 | 250 | ||
217 | if (ntoh24(mac) == FC_FCOE_OUI) | 251 | if (fp) { |
218 | fnic->fcoui_mode = 1; | 252 | mac = fr_cb(fp)->granted_mac; |
219 | else { | 253 | if (is_zero_ether_addr(mac)) { |
220 | fnic->fcoui_mode = 0; | 254 | /* non-FIP - FLOGI already accepted - ignore return */ |
221 | memcpy(fnic->dest_addr, mac, ETH_ALEN); | 255 | fcoe_ctlr_recv_flogi(&fnic->ctlr, lport, fp); |
222 | } | 256 | } |
257 | fnic_update_mac(lport, mac); | ||
258 | } | ||
223 | 259 | ||
224 | /* | 260 | /* Change state to reflect transition to FC mode */ |
225 | * Except for Flogi frame, all outbound frames from us have the | 261 | spin_lock_irq(&fnic->fnic_lock); |
226 | * Eth Src address as FC_FCOE_OUI"our_sid". Flogi frame uses | 262 | if (fnic->state == FNIC_IN_ETH_MODE || fnic->state == FNIC_IN_FC_MODE) |
227 | * the vnic MAC address as the Eth Src address | ||
228 | */ | ||
229 | fc_fcoe_set_mac(fnic->data_src_addr, fh->fh_d_id); | ||
230 | |||
231 | /* We get our s_id from the d_id of the flogi resp frame */ | ||
232 | fnic->s_id = ntoh24(fh->fh_d_id); | ||
233 | |||
234 | /* Change state to reflect transition from Eth to FC mode */ | ||
235 | fnic->state = FNIC_IN_ETH_TRANS_FC_MODE; | 263 | fnic->state = FNIC_IN_ETH_TRANS_FC_MODE; |
236 | 264 | else { | |
237 | } else { | ||
238 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | 265 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, |
239 | "Unexpected fnic state %s while" | 266 | "Unexpected fnic state %s while" |
240 | " processing flogi resp\n", | 267 | " processing flogi resp\n", |
241 | fnic_state_to_str(fnic->state)); | 268 | fnic_state_to_str(fnic->state)); |
242 | ret = -1; | 269 | spin_unlock_irq(&fnic->fnic_lock); |
243 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 270 | return; |
244 | dev_kfree_skb_irq(fp_skb(fp)); | ||
245 | goto handle_flogi_resp_end; | ||
246 | } | 271 | } |
247 | 272 | spin_unlock_irq(&fnic->fnic_lock); | |
248 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
249 | |||
250 | /* Drop older cached frame */ | ||
251 | if (old_flogi_resp) | ||
252 | dev_kfree_skb_irq(fp_skb(old_flogi_resp)); | ||
253 | 273 | ||
254 | /* | 274 | /* |
255 | * send flogi reg request to firmware, this will put the fnic in | 275 | * Send FLOGI registration to firmware to set up FC mode. |
256 | * in FC mode | 276 | * The new address will be set up when registration completes. |
257 | */ | 277 | */ |
258 | ret = fnic_flogi_reg_handler(fnic); | 278 | ret = fnic_flogi_reg_handler(fnic, port_id); |
259 | 279 | ||
260 | if (ret < 0) { | 280 | if (ret < 0) { |
261 | int free_fp = 1; | 281 | spin_lock_irq(&fnic->fnic_lock); |
262 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
263 | /* | ||
264 | * free the frame is some other thread is not | ||
265 | * pointing to it | ||
266 | */ | ||
267 | if (fnic->flogi_resp != fp) | ||
268 | free_fp = 0; | ||
269 | else | ||
270 | fnic->flogi_resp = NULL; | ||
271 | |||
272 | if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE) | 282 | if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE) |
273 | fnic->state = FNIC_IN_ETH_MODE; | 283 | fnic->state = FNIC_IN_ETH_MODE; |
274 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 284 | spin_unlock_irq(&fnic->fnic_lock); |
275 | if (free_fp) | ||
276 | dev_kfree_skb_irq(fp_skb(fp)); | ||
277 | } | 285 | } |
278 | |||
279 | handle_flogi_resp_end: | ||
280 | return ret; | ||
281 | } | ||
282 | |||
283 | /* Returns 1 for a response that matches cached flogi oxid */ | ||
284 | static inline int is_matching_flogi_resp_frame(struct fnic *fnic, | ||
285 | struct fc_frame *fp) | ||
286 | { | ||
287 | struct fc_frame_header *fh; | ||
288 | int ret = 0; | ||
289 | u32 f_ctl; | ||
290 | |||
291 | fh = fc_frame_header_get(fp); | ||
292 | f_ctl = ntoh24(fh->fh_f_ctl); | ||
293 | |||
294 | if (fnic->flogi_oxid == ntohs(fh->fh_ox_id) && | ||
295 | fh->fh_r_ctl == FC_RCTL_ELS_REP && | ||
296 | (f_ctl & (FC_FC_EX_CTX | FC_FC_SEQ_CTX)) == FC_FC_EX_CTX && | ||
297 | fh->fh_type == FC_TYPE_ELS) | ||
298 | ret = 1; | ||
299 | |||
300 | return ret; | ||
301 | } | 286 | } |
302 | 287 | ||
303 | static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc | 288 | static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc |
@@ -326,6 +311,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc | |||
326 | pci_unmap_single(fnic->pdev, buf->dma_addr, buf->len, | 311 | pci_unmap_single(fnic->pdev, buf->dma_addr, buf->len, |
327 | PCI_DMA_FROMDEVICE); | 312 | PCI_DMA_FROMDEVICE); |
328 | skb = buf->os_buf; | 313 | skb = buf->os_buf; |
314 | fp = (struct fc_frame *)skb; | ||
329 | buf->os_buf = NULL; | 315 | buf->os_buf = NULL; |
330 | 316 | ||
331 | cq_desc_dec(cq_desc, &type, &color, &q_number, &completed_index); | 317 | cq_desc_dec(cq_desc, &type, &color, &q_number, &completed_index); |
@@ -338,6 +324,9 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc | |||
338 | &fcoe_enc_error, &fcs_ok, &vlan_stripped, | 324 | &fcoe_enc_error, &fcs_ok, &vlan_stripped, |
339 | &vlan); | 325 | &vlan); |
340 | eth_hdrs_stripped = 1; | 326 | eth_hdrs_stripped = 1; |
327 | skb_trim(skb, fcp_bytes_written); | ||
328 | fr_sof(fp) = sof; | ||
329 | fr_eof(fp) = eof; | ||
341 | 330 | ||
342 | } else if (type == CQ_DESC_TYPE_RQ_ENET) { | 331 | } else if (type == CQ_DESC_TYPE_RQ_ENET) { |
343 | cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc, | 332 | cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc, |
@@ -352,6 +341,14 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc | |||
352 | &ipv4_csum_ok, &ipv6, &ipv4, | 341 | &ipv4_csum_ok, &ipv6, &ipv4, |
353 | &ipv4_fragment, &fcs_ok); | 342 | &ipv4_fragment, &fcs_ok); |
354 | eth_hdrs_stripped = 0; | 343 | eth_hdrs_stripped = 0; |
344 | skb_trim(skb, bytes_written); | ||
345 | if (!fcs_ok) { | ||
346 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | ||
347 | "fcs error. dropping packet.\n"); | ||
348 | goto drop; | ||
349 | } | ||
350 | if (fnic_import_rq_eth_pkt(fnic, skb)) | ||
351 | return; | ||
355 | 352 | ||
356 | } else { | 353 | } else { |
357 | /* wrong CQ type*/ | 354 | /* wrong CQ type*/ |
@@ -370,43 +367,11 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc | |||
370 | goto drop; | 367 | goto drop; |
371 | } | 368 | } |
372 | 369 | ||
373 | if (eth_hdrs_stripped) | ||
374 | fnic_import_rq_fc_frame(skb, fcp_bytes_written, sof, eof); | ||
375 | else if (fnic_import_rq_eth_pkt(skb, bytes_written)) | ||
376 | goto drop; | ||
377 | |||
378 | fp = (struct fc_frame *)skb; | ||
379 | |||
380 | /* | ||
381 | * If frame is an ELS response that matches the cached FLOGI OX_ID, | ||
382 | * and is accept, issue flogi_reg_request copy wq request to firmware | ||
383 | * to register the S_ID and determine whether FC_OUI mode or GW mode. | ||
384 | */ | ||
385 | if (is_matching_flogi_resp_frame(fnic, fp)) { | ||
386 | if (!eth_hdrs_stripped) { | ||
387 | if (fc_frame_payload_op(fp) == ELS_LS_ACC) { | ||
388 | fnic_handle_flogi_resp(fnic, fp); | ||
389 | return; | ||
390 | } | ||
391 | /* | ||
392 | * Recd. Flogi reject. No point registering | ||
393 | * with fw, but forward to libFC | ||
394 | */ | ||
395 | goto forward; | ||
396 | } | ||
397 | goto drop; | ||
398 | } | ||
399 | if (!eth_hdrs_stripped) | ||
400 | goto drop; | ||
401 | |||
402 | forward: | ||
403 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 370 | spin_lock_irqsave(&fnic->fnic_lock, flags); |
404 | if (fnic->stop_rx_link_events) { | 371 | if (fnic->stop_rx_link_events) { |
405 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 372 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
406 | goto drop; | 373 | goto drop; |
407 | } | 374 | } |
408 | /* Use fr_flags to indicate whether succ. flogi resp or not */ | ||
409 | fr_flags(fp) = 0; | ||
410 | fr_dev(fp) = fnic->lport; | 375 | fr_dev(fp) = fnic->lport; |
411 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 376 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
412 | 377 | ||
@@ -494,12 +459,49 @@ void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf) | |||
494 | buf->os_buf = NULL; | 459 | buf->os_buf = NULL; |
495 | } | 460 | } |
496 | 461 | ||
497 | static inline int is_flogi_frame(struct fc_frame_header *fh) | 462 | /** |
463 | * fnic_eth_send() - Send Ethernet frame. | ||
464 | * @fip: fcoe_ctlr instance. | ||
465 | * @skb: Ethernet Frame, FIP, without VLAN encapsulation. | ||
466 | */ | ||
467 | void fnic_eth_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | ||
498 | { | 468 | { |
499 | return fh->fh_r_ctl == FC_RCTL_ELS_REQ && *(u8 *)(fh + 1) == ELS_FLOGI; | 469 | struct fnic *fnic = fnic_from_ctlr(fip); |
470 | struct vnic_wq *wq = &fnic->wq[0]; | ||
471 | dma_addr_t pa; | ||
472 | struct ethhdr *eth_hdr; | ||
473 | struct vlan_ethhdr *vlan_hdr; | ||
474 | unsigned long flags; | ||
475 | |||
476 | if (!fnic->vlan_hw_insert) { | ||
477 | eth_hdr = (struct ethhdr *)skb_mac_header(skb); | ||
478 | vlan_hdr = (struct vlan_ethhdr *)skb_push(skb, | ||
479 | sizeof(*vlan_hdr) - sizeof(*eth_hdr)); | ||
480 | memcpy(vlan_hdr, eth_hdr, 2 * ETH_ALEN); | ||
481 | vlan_hdr->h_vlan_proto = htons(ETH_P_8021Q); | ||
482 | vlan_hdr->h_vlan_encapsulated_proto = eth_hdr->h_proto; | ||
483 | vlan_hdr->h_vlan_TCI = htons(fnic->vlan_id); | ||
484 | } | ||
485 | |||
486 | pa = pci_map_single(fnic->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); | ||
487 | |||
488 | spin_lock_irqsave(&fnic->wq_lock[0], flags); | ||
489 | if (!vnic_wq_desc_avail(wq)) { | ||
490 | pci_unmap_single(fnic->pdev, pa, skb->len, PCI_DMA_TODEVICE); | ||
491 | spin_unlock_irqrestore(&fnic->wq_lock[0], flags); | ||
492 | kfree_skb(skb); | ||
493 | return; | ||
494 | } | ||
495 | |||
496 | fnic_queue_wq_eth_desc(wq, skb, pa, skb->len, | ||
497 | fnic->vlan_hw_insert, fnic->vlan_id, 1); | ||
498 | spin_unlock_irqrestore(&fnic->wq_lock[0], flags); | ||
500 | } | 499 | } |
501 | 500 | ||
502 | int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp) | 501 | /* |
502 | * Send FC frame. | ||
503 | */ | ||
504 | static int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp) | ||
503 | { | 505 | { |
504 | struct vnic_wq *wq = &fnic->wq[0]; | 506 | struct vnic_wq *wq = &fnic->wq[0]; |
505 | struct sk_buff *skb; | 507 | struct sk_buff *skb; |
@@ -515,6 +517,10 @@ int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp) | |||
515 | fh = fc_frame_header_get(fp); | 517 | fh = fc_frame_header_get(fp); |
516 | skb = fp_skb(fp); | 518 | skb = fp_skb(fp); |
517 | 519 | ||
520 | if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && | ||
521 | fcoe_ctlr_els_send(&fnic->ctlr, fnic->lport, skb)) | ||
522 | return 0; | ||
523 | |||
518 | if (!fnic->vlan_hw_insert) { | 524 | if (!fnic->vlan_hw_insert) { |
519 | eth_hdr_len = sizeof(*vlan_hdr) + sizeof(*fcoe_hdr); | 525 | eth_hdr_len = sizeof(*vlan_hdr) + sizeof(*fcoe_hdr); |
520 | vlan_hdr = (struct vlan_ethhdr *)skb_push(skb, eth_hdr_len); | 526 | vlan_hdr = (struct vlan_ethhdr *)skb_push(skb, eth_hdr_len); |
@@ -530,16 +536,11 @@ int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp) | |||
530 | fcoe_hdr = (struct fcoe_hdr *)(eth_hdr + 1); | 536 | fcoe_hdr = (struct fcoe_hdr *)(eth_hdr + 1); |
531 | } | 537 | } |
532 | 538 | ||
533 | if (is_flogi_frame(fh)) { | 539 | if (fnic->ctlr.map_dest) |
534 | fc_fcoe_set_mac(eth_hdr->h_dest, fh->fh_d_id); | 540 | fc_fcoe_set_mac(eth_hdr->h_dest, fh->fh_d_id); |
535 | memcpy(eth_hdr->h_source, fnic->mac_addr, ETH_ALEN); | 541 | else |
536 | } else { | 542 | memcpy(eth_hdr->h_dest, fnic->ctlr.dest_addr, ETH_ALEN); |
537 | if (fnic->fcoui_mode) | 543 | memcpy(eth_hdr->h_source, fnic->data_src_addr, ETH_ALEN); |
538 | fc_fcoe_set_mac(eth_hdr->h_dest, fh->fh_d_id); | ||
539 | else | ||
540 | memcpy(eth_hdr->h_dest, fnic->dest_addr, ETH_ALEN); | ||
541 | memcpy(eth_hdr->h_source, fnic->data_src_addr, ETH_ALEN); | ||
542 | } | ||
543 | 544 | ||
544 | tot_len = skb->len; | 545 | tot_len = skb->len; |
545 | BUG_ON(tot_len % 4); | 546 | BUG_ON(tot_len % 4); |
@@ -578,109 +579,85 @@ fnic_send_frame_end: | |||
578 | int fnic_send(struct fc_lport *lp, struct fc_frame *fp) | 579 | int fnic_send(struct fc_lport *lp, struct fc_frame *fp) |
579 | { | 580 | { |
580 | struct fnic *fnic = lport_priv(lp); | 581 | struct fnic *fnic = lport_priv(lp); |
581 | struct fc_frame_header *fh; | ||
582 | int ret = 0; | ||
583 | enum fnic_state old_state; | ||
584 | unsigned long flags; | 582 | unsigned long flags; |
585 | struct fc_frame *old_flogi = NULL; | ||
586 | struct fc_frame *old_flogi_resp = NULL; | ||
587 | 583 | ||
588 | if (fnic->in_remove) { | 584 | if (fnic->in_remove) { |
589 | dev_kfree_skb(fp_skb(fp)); | 585 | dev_kfree_skb(fp_skb(fp)); |
590 | ret = -1; | 586 | return -1; |
591 | goto fnic_send_end; | ||
592 | } | 587 | } |
593 | 588 | ||
594 | fh = fc_frame_header_get(fp); | 589 | /* |
595 | /* if not an Flogi frame, send it out, this is the common case */ | 590 | * Queue frame if in a transitional state. |
596 | if (!is_flogi_frame(fh)) | 591 | * This occurs while registering the Port_ID / MAC address after FLOGI. |
597 | return fnic_send_frame(fnic, fp); | 592 | */ |
593 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
594 | if (fnic->state != FNIC_IN_FC_MODE && fnic->state != FNIC_IN_ETH_MODE) { | ||
595 | skb_queue_tail(&fnic->tx_queue, fp_skb(fp)); | ||
596 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
597 | return 0; | ||
598 | } | ||
599 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
598 | 600 | ||
599 | /* Flogi frame, now enter the state machine */ | 601 | return fnic_send_frame(fnic, fp); |
602 | } | ||
600 | 603 | ||
601 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 604 | /** |
602 | again: | 605 | * fnic_flush_tx() - send queued frames. |
603 | /* Get any old cached frames, free them after dropping lock */ | 606 | * @fnic: fnic device |
604 | old_flogi = fnic->flogi; | 607 | * |
605 | fnic->flogi = NULL; | 608 | * Send frames that were waiting to go out in FC or Ethernet mode. |
606 | old_flogi_resp = fnic->flogi_resp; | 609 | * Whenever changing modes we purge queued frames, so these frames should |
607 | fnic->flogi_resp = NULL; | 610 | * be queued for the stable mode that we're in, either FC or Ethernet. |
611 | * | ||
612 | * Called without fnic_lock held. | ||
613 | */ | ||
614 | void fnic_flush_tx(struct fnic *fnic) | ||
615 | { | ||
616 | struct sk_buff *skb; | ||
617 | struct fc_frame *fp; | ||
608 | 618 | ||
609 | fnic->flogi_oxid = FC_XID_UNKNOWN; | 619 | while ((skb = skb_dequeue(&fnic->frame_queue))) { |
620 | fp = (struct fc_frame *)skb; | ||
621 | fnic_send_frame(fnic, fp); | ||
622 | } | ||
623 | } | ||
610 | 624 | ||
625 | /** | ||
626 | * fnic_set_eth_mode() - put fnic into ethernet mode. | ||
627 | * @fnic: fnic device | ||
628 | * | ||
629 | * Called without fnic lock held. | ||
630 | */ | ||
631 | static void fnic_set_eth_mode(struct fnic *fnic) | ||
632 | { | ||
633 | unsigned long flags; | ||
634 | enum fnic_state old_state; | ||
635 | int ret; | ||
636 | |||
637 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
638 | again: | ||
611 | old_state = fnic->state; | 639 | old_state = fnic->state; |
612 | switch (old_state) { | 640 | switch (old_state) { |
613 | case FNIC_IN_FC_MODE: | 641 | case FNIC_IN_FC_MODE: |
614 | case FNIC_IN_ETH_TRANS_FC_MODE: | 642 | case FNIC_IN_ETH_TRANS_FC_MODE: |
615 | default: | 643 | default: |
616 | fnic->state = FNIC_IN_FC_TRANS_ETH_MODE; | 644 | fnic->state = FNIC_IN_FC_TRANS_ETH_MODE; |
617 | vnic_dev_del_addr(fnic->vdev, fnic->data_src_addr); | ||
618 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 645 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
619 | 646 | ||
620 | if (old_flogi) { | ||
621 | dev_kfree_skb(fp_skb(old_flogi)); | ||
622 | old_flogi = NULL; | ||
623 | } | ||
624 | if (old_flogi_resp) { | ||
625 | dev_kfree_skb(fp_skb(old_flogi_resp)); | ||
626 | old_flogi_resp = NULL; | ||
627 | } | ||
628 | |||
629 | ret = fnic_fw_reset_handler(fnic); | 647 | ret = fnic_fw_reset_handler(fnic); |
630 | 648 | ||
631 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 649 | spin_lock_irqsave(&fnic->fnic_lock, flags); |
632 | if (fnic->state != FNIC_IN_FC_TRANS_ETH_MODE) | 650 | if (fnic->state != FNIC_IN_FC_TRANS_ETH_MODE) |
633 | goto again; | 651 | goto again; |
634 | if (ret) { | 652 | if (ret) |
635 | fnic->state = old_state; | 653 | fnic->state = old_state; |
636 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
637 | dev_kfree_skb(fp_skb(fp)); | ||
638 | goto fnic_send_end; | ||
639 | } | ||
640 | old_flogi = fnic->flogi; | ||
641 | fnic->flogi = fp; | ||
642 | fnic->flogi_oxid = ntohs(fh->fh_ox_id); | ||
643 | old_flogi_resp = fnic->flogi_resp; | ||
644 | fnic->flogi_resp = NULL; | ||
645 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
646 | break; | 654 | break; |
647 | 655 | ||
648 | case FNIC_IN_FC_TRANS_ETH_MODE: | 656 | case FNIC_IN_FC_TRANS_ETH_MODE: |
649 | /* | ||
650 | * A reset is pending with the firmware. Store the flogi | ||
651 | * and its oxid. The transition out of this state happens | ||
652 | * only when Firmware completes the reset, either with | ||
653 | * success or failed. If success, transition to | ||
654 | * FNIC_IN_ETH_MODE, if fail, then transition to | ||
655 | * FNIC_IN_FC_MODE | ||
656 | */ | ||
657 | fnic->flogi = fp; | ||
658 | fnic->flogi_oxid = ntohs(fh->fh_ox_id); | ||
659 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
660 | break; | ||
661 | |||
662 | case FNIC_IN_ETH_MODE: | 657 | case FNIC_IN_ETH_MODE: |
663 | /* | ||
664 | * The fw/hw is already in eth mode. Store the oxid, | ||
665 | * and send the flogi frame out. The transition out of this | ||
666 | * state happens only we receive flogi response from the | ||
667 | * network, and the oxid matches the cached oxid when the | ||
668 | * flogi frame was sent out. If they match, then we issue | ||
669 | * a flogi_reg request and transition to state | ||
670 | * FNIC_IN_ETH_TRANS_FC_MODE | ||
671 | */ | ||
672 | fnic->flogi_oxid = ntohs(fh->fh_ox_id); | ||
673 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
674 | ret = fnic_send_frame(fnic, fp); | ||
675 | break; | 658 | break; |
676 | } | 659 | } |
677 | 660 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | |
678 | fnic_send_end: | ||
679 | if (old_flogi) | ||
680 | dev_kfree_skb(fp_skb(old_flogi)); | ||
681 | if (old_flogi_resp) | ||
682 | dev_kfree_skb(fp_skb(old_flogi_resp)); | ||
683 | return ret; | ||
684 | } | 661 | } |
685 | 662 | ||
686 | static void fnic_wq_complete_frame_send(struct vnic_wq *wq, | 663 | static void fnic_wq_complete_frame_send(struct vnic_wq *wq, |
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index 018cc427504a..0333c7f52e66 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
27 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
28 | #include <linux/if_ether.h> | ||
29 | #include <scsi/fc/fc_fip.h> | ||
28 | #include <scsi/scsi_host.h> | 30 | #include <scsi/scsi_host.h> |
29 | #include <scsi/scsi_transport.h> | 31 | #include <scsi/scsi_transport.h> |
30 | #include <scsi/scsi_transport_fc.h> | 32 | #include <scsi/scsi_transport_fc.h> |
@@ -68,6 +70,7 @@ MODULE_PARM_DESC(fnic_log_level, "bit mask of fnic logging levels"); | |||
68 | 70 | ||
69 | static struct libfc_function_template fnic_transport_template = { | 71 | static struct libfc_function_template fnic_transport_template = { |
70 | .frame_send = fnic_send, | 72 | .frame_send = fnic_send, |
73 | .lport_set_port_id = fnic_set_port_id, | ||
71 | .fcp_abort_io = fnic_empty_scsi_cleanup, | 74 | .fcp_abort_io = fnic_empty_scsi_cleanup, |
72 | .fcp_cleanup = fnic_empty_scsi_cleanup, | 75 | .fcp_cleanup = fnic_empty_scsi_cleanup, |
73 | .exch_mgr_reset = fnic_exch_mgr_reset | 76 | .exch_mgr_reset = fnic_exch_mgr_reset |
@@ -324,9 +327,6 @@ static int fnic_cleanup(struct fnic *fnic) | |||
324 | { | 327 | { |
325 | unsigned int i; | 328 | unsigned int i; |
326 | int err; | 329 | int err; |
327 | unsigned long flags; | ||
328 | struct fc_frame *flogi = NULL; | ||
329 | struct fc_frame *flogi_resp = NULL; | ||
330 | 330 | ||
331 | vnic_dev_disable(fnic->vdev); | 331 | vnic_dev_disable(fnic->vdev); |
332 | for (i = 0; i < fnic->intr_count; i++) | 332 | for (i = 0; i < fnic->intr_count; i++) |
@@ -367,24 +367,6 @@ static int fnic_cleanup(struct fnic *fnic) | |||
367 | for (i = 0; i < fnic->intr_count; i++) | 367 | for (i = 0; i < fnic->intr_count; i++) |
368 | vnic_intr_clean(&fnic->intr[i]); | 368 | vnic_intr_clean(&fnic->intr[i]); |
369 | 369 | ||
370 | /* | ||
371 | * Remove cached flogi and flogi resp frames if any | ||
372 | * These frames are not in any queue, and therefore queue | ||
373 | * cleanup does not clean them. So clean them explicitly | ||
374 | */ | ||
375 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
376 | flogi = fnic->flogi; | ||
377 | fnic->flogi = NULL; | ||
378 | flogi_resp = fnic->flogi_resp; | ||
379 | fnic->flogi_resp = NULL; | ||
380 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
381 | |||
382 | if (flogi) | ||
383 | dev_kfree_skb(fp_skb(flogi)); | ||
384 | |||
385 | if (flogi_resp) | ||
386 | dev_kfree_skb(fp_skb(flogi_resp)); | ||
387 | |||
388 | mempool_destroy(fnic->io_req_pool); | 370 | mempool_destroy(fnic->io_req_pool); |
389 | for (i = 0; i < FNIC_SGL_NUM_CACHES; i++) | 371 | for (i = 0; i < FNIC_SGL_NUM_CACHES; i++) |
390 | mempool_destroy(fnic->io_sgl_pool[i]); | 372 | mempool_destroy(fnic->io_sgl_pool[i]); |
@@ -409,6 +391,17 @@ static void *fnic_alloc_slab_dma(gfp_t gfp_mask, void *pool_data) | |||
409 | return kmem_cache_alloc(mem, gfp_mask | GFP_ATOMIC | GFP_DMA); | 391 | return kmem_cache_alloc(mem, gfp_mask | GFP_ATOMIC | GFP_DMA); |
410 | } | 392 | } |
411 | 393 | ||
394 | /** | ||
395 | * fnic_get_mac() - get assigned data MAC address for FIP code. | ||
396 | * @lport: local port. | ||
397 | */ | ||
398 | static u8 *fnic_get_mac(struct fc_lport *lport) | ||
399 | { | ||
400 | struct fnic *fnic = lport_priv(lport); | ||
401 | |||
402 | return fnic->data_src_addr; | ||
403 | } | ||
404 | |||
412 | static int __devinit fnic_probe(struct pci_dev *pdev, | 405 | static int __devinit fnic_probe(struct pci_dev *pdev, |
413 | const struct pci_device_id *ent) | 406 | const struct pci_device_id *ent) |
414 | { | 407 | { |
@@ -433,6 +426,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
433 | host = lp->host; | 426 | host = lp->host; |
434 | fnic = lport_priv(lp); | 427 | fnic = lport_priv(lp); |
435 | fnic->lport = lp; | 428 | fnic->lport = lp; |
429 | fnic->ctlr.lp = lp; | ||
436 | 430 | ||
437 | snprintf(fnic->name, sizeof(fnic->name) - 1, "%s%d", DRV_NAME, | 431 | snprintf(fnic->name, sizeof(fnic->name) - 1, "%s%d", DRV_NAME, |
438 | host->host_no); | 432 | host->host_no); |
@@ -541,12 +535,14 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
541 | goto err_out_dev_close; | 535 | goto err_out_dev_close; |
542 | } | 536 | } |
543 | 537 | ||
544 | err = vnic_dev_mac_addr(fnic->vdev, fnic->mac_addr); | 538 | err = vnic_dev_mac_addr(fnic->vdev, fnic->ctlr.ctl_src_addr); |
545 | if (err) { | 539 | if (err) { |
546 | shost_printk(KERN_ERR, fnic->lport->host, | 540 | shost_printk(KERN_ERR, fnic->lport->host, |
547 | "vNIC get MAC addr failed \n"); | 541 | "vNIC get MAC addr failed \n"); |
548 | goto err_out_dev_close; | 542 | goto err_out_dev_close; |
549 | } | 543 | } |
544 | /* set data_src for point-to-point mode and to keep it non-zero */ | ||
545 | memcpy(fnic->data_src_addr, fnic->ctlr.ctl_src_addr, ETH_ALEN); | ||
550 | 546 | ||
551 | /* Get vNIC configuration */ | 547 | /* Get vNIC configuration */ |
552 | err = fnic_get_vnic_config(fnic); | 548 | err = fnic_get_vnic_config(fnic); |
@@ -615,9 +611,21 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
615 | fnic->vlan_hw_insert = 1; | 611 | fnic->vlan_hw_insert = 1; |
616 | fnic->vlan_id = 0; | 612 | fnic->vlan_id = 0; |
617 | 613 | ||
618 | fnic->flogi_oxid = FC_XID_UNKNOWN; | 614 | /* Initialize the FIP fcoe_ctrl struct */ |
619 | fnic->flogi = NULL; | 615 | fnic->ctlr.send = fnic_eth_send; |
620 | fnic->flogi_resp = NULL; | 616 | fnic->ctlr.update_mac = fnic_update_mac; |
617 | fnic->ctlr.get_src_addr = fnic_get_mac; | ||
618 | fcoe_ctlr_init(&fnic->ctlr); | ||
619 | if (fnic->config.flags & VFCF_FIP_CAPABLE) { | ||
620 | shost_printk(KERN_INFO, fnic->lport->host, | ||
621 | "firmware supports FIP\n"); | ||
622 | vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS); | ||
623 | vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr); | ||
624 | } else { | ||
625 | shost_printk(KERN_INFO, fnic->lport->host, | ||
626 | "firmware uses non-FIP mode\n"); | ||
627 | fnic->ctlr.mode = FIP_ST_NON_FIP; | ||
628 | } | ||
621 | fnic->state = FNIC_IN_FC_MODE; | 629 | fnic->state = FNIC_IN_FC_MODE; |
622 | 630 | ||
623 | /* Enable hardware stripping of vlan header on ingress */ | 631 | /* Enable hardware stripping of vlan header on ingress */ |
@@ -708,6 +716,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
708 | INIT_WORK(&fnic->link_work, fnic_handle_link); | 716 | INIT_WORK(&fnic->link_work, fnic_handle_link); |
709 | INIT_WORK(&fnic->frame_work, fnic_handle_frame); | 717 | INIT_WORK(&fnic->frame_work, fnic_handle_frame); |
710 | skb_queue_head_init(&fnic->frame_queue); | 718 | skb_queue_head_init(&fnic->frame_queue); |
719 | skb_queue_head_init(&fnic->tx_queue); | ||
711 | 720 | ||
712 | /* Enable all queues */ | 721 | /* Enable all queues */ |
713 | for (i = 0; i < fnic->raw_wq_count; i++) | 722 | for (i = 0; i < fnic->raw_wq_count; i++) |
@@ -738,8 +747,8 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
738 | err_out_free_exch_mgr: | 747 | err_out_free_exch_mgr: |
739 | fc_exch_mgr_free(lp); | 748 | fc_exch_mgr_free(lp); |
740 | err_out_remove_scsi_host: | 749 | err_out_remove_scsi_host: |
741 | fc_remove_host(fnic->lport->host); | 750 | fc_remove_host(lp->host); |
742 | scsi_remove_host(fnic->lport->host); | 751 | scsi_remove_host(lp->host); |
743 | err_out_free_rq_buf: | 752 | err_out_free_rq_buf: |
744 | for (i = 0; i < fnic->rq_count; i++) | 753 | for (i = 0; i < fnic->rq_count; i++) |
745 | vnic_rq_clean(&fnic->rq[i], fnic_free_rq_buf); | 754 | vnic_rq_clean(&fnic->rq[i], fnic_free_rq_buf); |
@@ -773,6 +782,7 @@ err_out: | |||
773 | static void __devexit fnic_remove(struct pci_dev *pdev) | 782 | static void __devexit fnic_remove(struct pci_dev *pdev) |
774 | { | 783 | { |
775 | struct fnic *fnic = pci_get_drvdata(pdev); | 784 | struct fnic *fnic = pci_get_drvdata(pdev); |
785 | struct fc_lport *lp = fnic->lport; | ||
776 | unsigned long flags; | 786 | unsigned long flags; |
777 | 787 | ||
778 | /* | 788 | /* |
@@ -794,6 +804,7 @@ static void __devexit fnic_remove(struct pci_dev *pdev) | |||
794 | */ | 804 | */ |
795 | flush_workqueue(fnic_event_queue); | 805 | flush_workqueue(fnic_event_queue); |
796 | skb_queue_purge(&fnic->frame_queue); | 806 | skb_queue_purge(&fnic->frame_queue); |
807 | skb_queue_purge(&fnic->tx_queue); | ||
797 | 808 | ||
798 | /* | 809 | /* |
799 | * Log off the fabric. This stops all remote ports, dns port, | 810 | * Log off the fabric. This stops all remote ports, dns port, |
@@ -806,7 +817,8 @@ static void __devexit fnic_remove(struct pci_dev *pdev) | |||
806 | fnic->in_remove = 1; | 817 | fnic->in_remove = 1; |
807 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 818 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
808 | 819 | ||
809 | fc_lport_destroy(fnic->lport); | 820 | fcoe_ctlr_destroy(&fnic->ctlr); |
821 | fc_lport_destroy(lp); | ||
810 | 822 | ||
811 | /* | 823 | /* |
812 | * This stops the fnic device, masks all interrupts. Completed | 824 | * This stops the fnic device, masks all interrupts. Completed |
@@ -816,6 +828,7 @@ static void __devexit fnic_remove(struct pci_dev *pdev) | |||
816 | fnic_cleanup(fnic); | 828 | fnic_cleanup(fnic); |
817 | 829 | ||
818 | BUG_ON(!skb_queue_empty(&fnic->frame_queue)); | 830 | BUG_ON(!skb_queue_empty(&fnic->frame_queue)); |
831 | BUG_ON(!skb_queue_empty(&fnic->tx_queue)); | ||
819 | 832 | ||
820 | spin_lock_irqsave(&fnic_list_lock, flags); | 833 | spin_lock_irqsave(&fnic_list_lock, flags); |
821 | list_del(&fnic->list); | 834 | list_del(&fnic->list); |
@@ -834,7 +847,7 @@ static void __devexit fnic_remove(struct pci_dev *pdev) | |||
834 | pci_release_regions(pdev); | 847 | pci_release_regions(pdev); |
835 | pci_disable_device(pdev); | 848 | pci_disable_device(pdev); |
836 | pci_set_drvdata(pdev, NULL); | 849 | pci_set_drvdata(pdev, NULL); |
837 | scsi_host_put(fnic->lport->host); | 850 | scsi_host_put(lp->host); |
838 | } | 851 | } |
839 | 852 | ||
840 | static struct pci_driver fnic_driver = { | 853 | static struct pci_driver fnic_driver = { |
diff --git a/drivers/scsi/fnic/fnic_res.c b/drivers/scsi/fnic/fnic_res.c index 7ba61ec715d2..50488f8e169d 100644 --- a/drivers/scsi/fnic/fnic_res.c +++ b/drivers/scsi/fnic/fnic_res.c | |||
@@ -144,10 +144,9 @@ int fnic_get_vnic_config(struct fnic *fnic) | |||
144 | c->intr_timer_type = c->intr_timer_type; | 144 | c->intr_timer_type = c->intr_timer_type; |
145 | 145 | ||
146 | shost_printk(KERN_INFO, fnic->lport->host, | 146 | shost_printk(KERN_INFO, fnic->lport->host, |
147 | "vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x " | 147 | "vNIC MAC addr %pM " |
148 | "wq/wq_copy/rq %d/%d/%d\n", | 148 | "wq/wq_copy/rq %d/%d/%d\n", |
149 | fnic->mac_addr[0], fnic->mac_addr[1], fnic->mac_addr[2], | 149 | fnic->ctlr.ctl_src_addr, |
150 | fnic->mac_addr[3], fnic->mac_addr[4], fnic->mac_addr[5], | ||
151 | c->wq_enet_desc_count, c->wq_copy_desc_count, | 150 | c->wq_enet_desc_count, c->wq_copy_desc_count, |
152 | c->rq_desc_count); | 151 | c->rq_desc_count); |
153 | shost_printk(KERN_INFO, fnic->lport->host, | 152 | shost_printk(KERN_INFO, fnic->lport->host, |
diff --git a/drivers/scsi/fnic/fnic_res.h b/drivers/scsi/fnic/fnic_res.h index 88c4471c18f0..ef8aaf2156dd 100644 --- a/drivers/scsi/fnic/fnic_res.h +++ b/drivers/scsi/fnic/fnic_res.h | |||
@@ -51,6 +51,31 @@ static inline void fnic_queue_wq_desc(struct vnic_wq *wq, | |||
51 | vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop); | 51 | vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop); |
52 | } | 52 | } |
53 | 53 | ||
54 | static inline void fnic_queue_wq_eth_desc(struct vnic_wq *wq, | ||
55 | void *os_buf, dma_addr_t dma_addr, | ||
56 | unsigned int len, | ||
57 | int vlan_tag_insert, | ||
58 | unsigned int vlan_tag, | ||
59 | int cq_entry) | ||
60 | { | ||
61 | struct wq_enet_desc *desc = vnic_wq_next_desc(wq); | ||
62 | |||
63 | wq_enet_desc_enc(desc, | ||
64 | (u64)dma_addr | VNIC_PADDR_TARGET, | ||
65 | (u16)len, | ||
66 | 0, /* mss_or_csum_offset */ | ||
67 | 0, /* fc_eof */ | ||
68 | 0, /* offload_mode */ | ||
69 | 1, /* eop */ | ||
70 | (u8)cq_entry, | ||
71 | 0, /* fcoe_encap */ | ||
72 | (u8)vlan_tag_insert, | ||
73 | (u16)vlan_tag, | ||
74 | 0 /* loopback */); | ||
75 | |||
76 | vnic_wq_post(wq, os_buf, dma_addr, len, 1, 1); | ||
77 | } | ||
78 | |||
54 | static inline void fnic_queue_wq_copy_desc_icmnd_16(struct vnic_wq_copy *wq, | 79 | static inline void fnic_queue_wq_copy_desc_icmnd_16(struct vnic_wq_copy *wq, |
55 | u32 req_id, | 80 | u32 req_id, |
56 | u32 lunmap_id, u8 spl_flags, | 81 | u32 lunmap_id, u8 spl_flags, |
@@ -134,12 +159,37 @@ static inline void fnic_queue_wq_copy_desc_flogi_reg(struct vnic_wq_copy *wq, | |||
134 | desc->hdr.tag.u.req_id = req_id; /* id for this request */ | 159 | desc->hdr.tag.u.req_id = req_id; /* id for this request */ |
135 | 160 | ||
136 | desc->u.flogi_reg.format = format; | 161 | desc->u.flogi_reg.format = format; |
162 | desc->u.flogi_reg._resvd = 0; | ||
137 | hton24(desc->u.flogi_reg.s_id, s_id); | 163 | hton24(desc->u.flogi_reg.s_id, s_id); |
138 | memcpy(desc->u.flogi_reg.gateway_mac, gw_mac, ETH_ALEN); | 164 | memcpy(desc->u.flogi_reg.gateway_mac, gw_mac, ETH_ALEN); |
139 | 165 | ||
140 | vnic_wq_copy_post(wq); | 166 | vnic_wq_copy_post(wq); |
141 | } | 167 | } |
142 | 168 | ||
169 | static inline void fnic_queue_wq_copy_desc_fip_reg(struct vnic_wq_copy *wq, | ||
170 | u32 req_id, u32 s_id, | ||
171 | u8 *fcf_mac, u8 *ha_mac, | ||
172 | u32 r_a_tov, u32 e_d_tov) | ||
173 | { | ||
174 | struct fcpio_host_req *desc = vnic_wq_copy_next_desc(wq); | ||
175 | |||
176 | desc->hdr.type = FCPIO_FLOGI_FIP_REG; /* enum fcpio_type */ | ||
177 | desc->hdr.status = 0; /* header status entry */ | ||
178 | desc->hdr._resvd = 0; /* reserved */ | ||
179 | desc->hdr.tag.u.req_id = req_id; /* id for this request */ | ||
180 | |||
181 | desc->u.flogi_fip_reg._resvd0 = 0; | ||
182 | hton24(desc->u.flogi_fip_reg.s_id, s_id); | ||
183 | memcpy(desc->u.flogi_fip_reg.fcf_mac, fcf_mac, ETH_ALEN); | ||
184 | desc->u.flogi_fip_reg._resvd1 = 0; | ||
185 | desc->u.flogi_fip_reg.r_a_tov = r_a_tov; | ||
186 | desc->u.flogi_fip_reg.e_d_tov = e_d_tov; | ||
187 | memcpy(desc->u.flogi_fip_reg.ha_mac, ha_mac, ETH_ALEN); | ||
188 | desc->u.flogi_fip_reg._resvd2 = 0; | ||
189 | |||
190 | vnic_wq_copy_post(wq); | ||
191 | } | ||
192 | |||
143 | static inline void fnic_queue_wq_copy_desc_fw_reset(struct vnic_wq_copy *wq, | 193 | static inline void fnic_queue_wq_copy_desc_fw_reset(struct vnic_wq_copy *wq, |
144 | u32 req_id) | 194 | u32 req_id) |
145 | { | 195 | { |
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 8d26d7a9f01b..65a39b0f6dc2 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c | |||
@@ -174,6 +174,9 @@ int fnic_fw_reset_handler(struct fnic *fnic) | |||
174 | int ret = 0; | 174 | int ret = 0; |
175 | unsigned long flags; | 175 | unsigned long flags; |
176 | 176 | ||
177 | skb_queue_purge(&fnic->frame_queue); | ||
178 | skb_queue_purge(&fnic->tx_queue); | ||
179 | |||
177 | spin_lock_irqsave(&fnic->wq_copy_lock[0], flags); | 180 | spin_lock_irqsave(&fnic->wq_copy_lock[0], flags); |
178 | 181 | ||
179 | if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0]) | 182 | if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0]) |
@@ -200,9 +203,11 @@ int fnic_fw_reset_handler(struct fnic *fnic) | |||
200 | * fnic_flogi_reg_handler | 203 | * fnic_flogi_reg_handler |
201 | * Routine to send flogi register msg to fw | 204 | * Routine to send flogi register msg to fw |
202 | */ | 205 | */ |
203 | int fnic_flogi_reg_handler(struct fnic *fnic) | 206 | int fnic_flogi_reg_handler(struct fnic *fnic, u32 fc_id) |
204 | { | 207 | { |
205 | struct vnic_wq_copy *wq = &fnic->wq_copy[0]; | 208 | struct vnic_wq_copy *wq = &fnic->wq_copy[0]; |
209 | enum fcpio_flogi_reg_format_type format; | ||
210 | struct fc_lport *lp = fnic->lport; | ||
206 | u8 gw_mac[ETH_ALEN]; | 211 | u8 gw_mac[ETH_ALEN]; |
207 | int ret = 0; | 212 | int ret = 0; |
208 | unsigned long flags; | 213 | unsigned long flags; |
@@ -217,23 +222,32 @@ int fnic_flogi_reg_handler(struct fnic *fnic) | |||
217 | goto flogi_reg_ioreq_end; | 222 | goto flogi_reg_ioreq_end; |
218 | } | 223 | } |
219 | 224 | ||
220 | if (fnic->fcoui_mode) | 225 | if (fnic->ctlr.map_dest) { |
221 | memset(gw_mac, 0xff, ETH_ALEN); | 226 | memset(gw_mac, 0xff, ETH_ALEN); |
222 | else | 227 | format = FCPIO_FLOGI_REG_DEF_DEST; |
223 | memcpy(gw_mac, fnic->dest_addr, ETH_ALEN); | 228 | } else { |
229 | memcpy(gw_mac, fnic->ctlr.dest_addr, ETH_ALEN); | ||
230 | format = FCPIO_FLOGI_REG_GW_DEST; | ||
231 | } | ||
224 | 232 | ||
225 | fnic_queue_wq_copy_desc_flogi_reg(wq, SCSI_NO_TAG, | 233 | if ((fnic->config.flags & VFCF_FIP_CAPABLE) && !fnic->ctlr.map_dest) { |
226 | FCPIO_FLOGI_REG_GW_DEST, | 234 | fnic_queue_wq_copy_desc_fip_reg(wq, SCSI_NO_TAG, |
227 | fnic->s_id, | 235 | fc_id, gw_mac, |
228 | gw_mac); | 236 | fnic->data_src_addr, |
237 | lp->r_a_tov, lp->e_d_tov); | ||
238 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | ||
239 | "FLOGI FIP reg issued fcid %x src %pM dest %pM\n", | ||
240 | fc_id, fnic->data_src_addr, gw_mac); | ||
241 | } else { | ||
242 | fnic_queue_wq_copy_desc_flogi_reg(wq, SCSI_NO_TAG, | ||
243 | format, fc_id, gw_mac); | ||
244 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | ||
245 | "FLOGI reg issued fcid %x map %d dest %pM\n", | ||
246 | fc_id, fnic->ctlr.map_dest, gw_mac); | ||
247 | } | ||
229 | 248 | ||
230 | flogi_reg_ioreq_end: | 249 | flogi_reg_ioreq_end: |
231 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); | 250 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); |
232 | |||
233 | if (!ret) | ||
234 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | ||
235 | "flog reg issued\n"); | ||
236 | |||
237 | return ret; | 251 | return ret; |
238 | } | 252 | } |
239 | 253 | ||
@@ -453,7 +467,6 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic, | |||
453 | u8 hdr_status; | 467 | u8 hdr_status; |
454 | struct fcpio_tag tag; | 468 | struct fcpio_tag tag; |
455 | int ret = 0; | 469 | int ret = 0; |
456 | struct fc_frame *flogi; | ||
457 | unsigned long flags; | 470 | unsigned long flags; |
458 | 471 | ||
459 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); | 472 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); |
@@ -463,9 +476,6 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic, | |||
463 | 476 | ||
464 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 477 | spin_lock_irqsave(&fnic->fnic_lock, flags); |
465 | 478 | ||
466 | flogi = fnic->flogi; | ||
467 | fnic->flogi = NULL; | ||
468 | |||
469 | /* fnic should be in FC_TRANS_ETH_MODE */ | 479 | /* fnic should be in FC_TRANS_ETH_MODE */ |
470 | if (fnic->state == FNIC_IN_FC_TRANS_ETH_MODE) { | 480 | if (fnic->state == FNIC_IN_FC_TRANS_ETH_MODE) { |
471 | /* Check status of reset completion */ | 481 | /* Check status of reset completion */ |
@@ -506,17 +516,14 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic, | |||
506 | * free the flogi frame. Else, send it out | 516 | * free the flogi frame. Else, send it out |
507 | */ | 517 | */ |
508 | if (fnic->remove_wait || ret) { | 518 | if (fnic->remove_wait || ret) { |
509 | fnic->flogi_oxid = FC_XID_UNKNOWN; | ||
510 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 519 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
511 | if (flogi) | 520 | skb_queue_purge(&fnic->tx_queue); |
512 | dev_kfree_skb_irq(fp_skb(flogi)); | ||
513 | goto reset_cmpl_handler_end; | 521 | goto reset_cmpl_handler_end; |
514 | } | 522 | } |
515 | 523 | ||
516 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 524 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
517 | 525 | ||
518 | if (flogi) | 526 | fnic_flush_tx(fnic); |
519 | ret = fnic_send_frame(fnic, flogi); | ||
520 | 527 | ||
521 | reset_cmpl_handler_end: | 528 | reset_cmpl_handler_end: |
522 | return ret; | 529 | return ret; |
@@ -533,18 +540,13 @@ static int fnic_fcpio_flogi_reg_cmpl_handler(struct fnic *fnic, | |||
533 | u8 hdr_status; | 540 | u8 hdr_status; |
534 | struct fcpio_tag tag; | 541 | struct fcpio_tag tag; |
535 | int ret = 0; | 542 | int ret = 0; |
536 | struct fc_frame *flogi_resp = NULL; | ||
537 | unsigned long flags; | 543 | unsigned long flags; |
538 | struct sk_buff *skb; | ||
539 | 544 | ||
540 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); | 545 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); |
541 | 546 | ||
542 | /* Update fnic state based on status of flogi reg completion */ | 547 | /* Update fnic state based on status of flogi reg completion */ |
543 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 548 | spin_lock_irqsave(&fnic->fnic_lock, flags); |
544 | 549 | ||
545 | flogi_resp = fnic->flogi_resp; | ||
546 | fnic->flogi_resp = NULL; | ||
547 | |||
548 | if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE) { | 550 | if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE) { |
549 | 551 | ||
550 | /* Check flogi registration completion status */ | 552 | /* Check flogi registration completion status */ |
@@ -568,25 +570,17 @@ static int fnic_fcpio_flogi_reg_cmpl_handler(struct fnic *fnic, | |||
568 | ret = -1; | 570 | ret = -1; |
569 | } | 571 | } |
570 | 572 | ||
571 | /* Successful flogi reg cmpl, pass frame to LibFC */ | 573 | if (!ret) { |
572 | if (!ret && flogi_resp) { | ||
573 | if (fnic->stop_rx_link_events) { | 574 | if (fnic->stop_rx_link_events) { |
574 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 575 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
575 | goto reg_cmpl_handler_end; | 576 | goto reg_cmpl_handler_end; |
576 | } | 577 | } |
577 | skb = (struct sk_buff *)flogi_resp; | ||
578 | /* Use fr_flags to indicate whether flogi resp or not */ | ||
579 | fr_flags(flogi_resp) = 1; | ||
580 | fr_dev(flogi_resp) = fnic->lport; | ||
581 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 578 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
582 | 579 | ||
583 | skb_queue_tail(&fnic->frame_queue, skb); | 580 | fnic_flush_tx(fnic); |
584 | queue_work(fnic_event_queue, &fnic->frame_work); | 581 | queue_work(fnic_event_queue, &fnic->frame_work); |
585 | |||
586 | } else { | 582 | } else { |
587 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 583 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
588 | if (flogi_resp) | ||
589 | dev_kfree_skb_irq(fp_skb(flogi_resp)); | ||
590 | } | 584 | } |
591 | 585 | ||
592 | reg_cmpl_handler_end: | 586 | reg_cmpl_handler_end: |
@@ -908,6 +902,7 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev, | |||
908 | break; | 902 | break; |
909 | 903 | ||
910 | case FCPIO_FLOGI_REG_CMPL: /* fw completed flogi_reg */ | 904 | case FCPIO_FLOGI_REG_CMPL: /* fw completed flogi_reg */ |
905 | case FCPIO_FLOGI_FIP_REG_CMPL: /* fw completed flogi_fip_reg */ | ||
911 | ret = fnic_fcpio_flogi_reg_cmpl_handler(fnic, desc); | 906 | ret = fnic_fcpio_flogi_reg_cmpl_handler(fnic, desc); |
912 | break; | 907 | break; |
913 | 908 | ||
@@ -1747,7 +1742,7 @@ void fnic_scsi_abort_io(struct fc_lport *lp) | |||
1747 | fnic->remove_wait = &remove_wait; | 1742 | fnic->remove_wait = &remove_wait; |
1748 | old_state = fnic->state; | 1743 | old_state = fnic->state; |
1749 | fnic->state = FNIC_IN_FC_TRANS_ETH_MODE; | 1744 | fnic->state = FNIC_IN_FC_TRANS_ETH_MODE; |
1750 | vnic_dev_del_addr(fnic->vdev, fnic->data_src_addr); | 1745 | fnic_update_mac_locked(fnic, fnic->ctlr.ctl_src_addr); |
1751 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 1746 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
1752 | 1747 | ||
1753 | err = fnic_fw_reset_handler(fnic); | 1748 | err = fnic_fw_reset_handler(fnic); |
@@ -1787,7 +1782,7 @@ void fnic_scsi_cleanup(struct fc_lport *lp) | |||
1787 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 1782 | spin_lock_irqsave(&fnic->fnic_lock, flags); |
1788 | old_state = fnic->state; | 1783 | old_state = fnic->state; |
1789 | fnic->state = FNIC_IN_FC_TRANS_ETH_MODE; | 1784 | fnic->state = FNIC_IN_FC_TRANS_ETH_MODE; |
1790 | vnic_dev_del_addr(fnic->vdev, fnic->data_src_addr); | 1785 | fnic_update_mac_locked(fnic, fnic->ctlr.ctl_src_addr); |
1791 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 1786 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
1792 | 1787 | ||
1793 | if (fnic_fw_reset_handler(fnic)) { | 1788 | if (fnic_fw_reset_handler(fnic)) { |
diff --git a/drivers/scsi/fnic/vnic_scsi.h b/drivers/scsi/fnic/vnic_scsi.h index 46baa5254001..fbb55364e272 100644 --- a/drivers/scsi/fnic/vnic_scsi.h +++ b/drivers/scsi/fnic/vnic_scsi.h | |||
@@ -95,5 +95,6 @@ struct vnic_fc_config { | |||
95 | 95 | ||
96 | #define VFCF_FCP_SEQ_LVL_ERR 0x1 /* Enable FCP-2 Error Recovery */ | 96 | #define VFCF_FCP_SEQ_LVL_ERR 0x1 /* Enable FCP-2 Error Recovery */ |
97 | #define VFCF_PERBI 0x2 /* persistent binding info available */ | 97 | #define VFCF_PERBI 0x2 /* persistent binding info available */ |
98 | #define VFCF_FIP_CAPABLE 0x4 /* firmware can handle FIP */ | ||
98 | 99 | ||
99 | #endif /* _VNIC_SCSI_H_ */ | 100 | #endif /* _VNIC_SCSI_H_ */ |