diff options
Diffstat (limited to 'drivers/scsi/fcoe/fcoe_ctlr.c')
-rw-r--r-- | drivers/scsi/fcoe/fcoe_ctlr.c | 148 |
1 files changed, 95 insertions, 53 deletions
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 203415e02518..34a1b1f333b4 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c | |||
@@ -160,74 +160,113 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode) | |||
160 | } | 160 | } |
161 | EXPORT_SYMBOL(fcoe_ctlr_init); | 161 | EXPORT_SYMBOL(fcoe_ctlr_init); |
162 | 162 | ||
163 | /** | ||
164 | * fcoe_sysfs_fcf_add() - Add a fcoe_fcf{,_device} to a fcoe_ctlr{,_device} | ||
165 | * @new: The newly discovered FCF | ||
166 | * | ||
167 | * Called with fip->ctlr_mutex held | ||
168 | */ | ||
163 | static int fcoe_sysfs_fcf_add(struct fcoe_fcf *new) | 169 | static int fcoe_sysfs_fcf_add(struct fcoe_fcf *new) |
164 | { | 170 | { |
165 | struct fcoe_ctlr *fip = new->fip; | 171 | struct fcoe_ctlr *fip = new->fip; |
166 | struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); | 172 | struct fcoe_ctlr_device *ctlr_dev; |
167 | struct fcoe_fcf_device temp, *fcf_dev; | 173 | struct fcoe_fcf_device *temp, *fcf_dev; |
168 | int rc = 0; | 174 | int rc = -ENOMEM; |
169 | 175 | ||
170 | LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n", | 176 | LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n", |
171 | new->fabric_name, new->fcf_mac); | 177 | new->fabric_name, new->fcf_mac); |
172 | 178 | ||
173 | mutex_lock(&ctlr_dev->lock); | 179 | temp = kzalloc(sizeof(*temp), GFP_KERNEL); |
174 | 180 | if (!temp) | |
175 | temp.fabric_name = new->fabric_name; | ||
176 | temp.switch_name = new->switch_name; | ||
177 | temp.fc_map = new->fc_map; | ||
178 | temp.vfid = new->vfid; | ||
179 | memcpy(temp.mac, new->fcf_mac, ETH_ALEN); | ||
180 | temp.priority = new->pri; | ||
181 | temp.fka_period = new->fka_period; | ||
182 | temp.selected = 0; /* default to unselected */ | ||
183 | |||
184 | fcf_dev = fcoe_fcf_device_add(ctlr_dev, &temp); | ||
185 | if (unlikely(!fcf_dev)) { | ||
186 | rc = -ENOMEM; | ||
187 | goto out; | 181 | goto out; |
188 | } | 182 | |
183 | temp->fabric_name = new->fabric_name; | ||
184 | temp->switch_name = new->switch_name; | ||
185 | temp->fc_map = new->fc_map; | ||
186 | temp->vfid = new->vfid; | ||
187 | memcpy(temp->mac, new->fcf_mac, ETH_ALEN); | ||
188 | temp->priority = new->pri; | ||
189 | temp->fka_period = new->fka_period; | ||
190 | temp->selected = 0; /* default to unselected */ | ||
189 | 191 | ||
190 | /* | 192 | /* |
191 | * The fcoe_sysfs layer can return a CONNECTED fcf that | 193 | * If ctlr_dev doesn't exist then it means we're a libfcoe user |
192 | * has a priv (fcf was never deleted) or a CONNECTED fcf | 194 | * who doesn't use fcoe_syfs and didn't allocate a fcoe_ctlr_device. |
193 | * that doesn't have a priv (fcf was deleted). However, | 195 | * fnic would be an example of a driver with this behavior. In this |
194 | * libfcoe will always delete FCFs before trying to add | 196 | * case we want to add the fcoe_fcf to the fcoe_ctlr list, but we |
195 | * them. This is ensured because both recv_adv and | 197 | * don't want to make sysfs changes. |
196 | * age_fcfs are protected by the the fcoe_ctlr's mutex. | ||
197 | * This means that we should never get a FCF with a | ||
198 | * non-NULL priv pointer. | ||
199 | */ | 198 | */ |
200 | BUG_ON(fcf_dev->priv); | ||
201 | 199 | ||
202 | fcf_dev->priv = new; | 200 | ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); |
203 | new->fcf_dev = fcf_dev; | 201 | if (ctlr_dev) { |
202 | mutex_lock(&ctlr_dev->lock); | ||
203 | fcf_dev = fcoe_fcf_device_add(ctlr_dev, temp); | ||
204 | if (unlikely(!fcf_dev)) { | ||
205 | rc = -ENOMEM; | ||
206 | mutex_unlock(&ctlr_dev->lock); | ||
207 | goto out; | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * The fcoe_sysfs layer can return a CONNECTED fcf that | ||
212 | * has a priv (fcf was never deleted) or a CONNECTED fcf | ||
213 | * that doesn't have a priv (fcf was deleted). However, | ||
214 | * libfcoe will always delete FCFs before trying to add | ||
215 | * them. This is ensured because both recv_adv and | ||
216 | * age_fcfs are protected by the the fcoe_ctlr's mutex. | ||
217 | * This means that we should never get a FCF with a | ||
218 | * non-NULL priv pointer. | ||
219 | */ | ||
220 | BUG_ON(fcf_dev->priv); | ||
221 | |||
222 | fcf_dev->priv = new; | ||
223 | new->fcf_dev = fcf_dev; | ||
224 | mutex_unlock(&ctlr_dev->lock); | ||
225 | } | ||
204 | 226 | ||
205 | list_add(&new->list, &fip->fcfs); | 227 | list_add(&new->list, &fip->fcfs); |
206 | fip->fcf_count++; | 228 | fip->fcf_count++; |
229 | rc = 0; | ||
207 | 230 | ||
208 | out: | 231 | out: |
209 | mutex_unlock(&ctlr_dev->lock); | 232 | kfree(temp); |
210 | return rc; | 233 | return rc; |
211 | } | 234 | } |
212 | 235 | ||
236 | /** | ||
237 | * fcoe_sysfs_fcf_del() - Remove a fcoe_fcf{,_device} to a fcoe_ctlr{,_device} | ||
238 | * @new: The FCF to be removed | ||
239 | * | ||
240 | * Called with fip->ctlr_mutex held | ||
241 | */ | ||
213 | static void fcoe_sysfs_fcf_del(struct fcoe_fcf *new) | 242 | static void fcoe_sysfs_fcf_del(struct fcoe_fcf *new) |
214 | { | 243 | { |
215 | struct fcoe_ctlr *fip = new->fip; | 244 | struct fcoe_ctlr *fip = new->fip; |
216 | struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); | 245 | struct fcoe_ctlr_device *cdev; |
217 | struct fcoe_fcf_device *fcf_dev; | 246 | struct fcoe_fcf_device *fcf_dev; |
218 | 247 | ||
219 | list_del(&new->list); | 248 | list_del(&new->list); |
220 | fip->fcf_count--; | 249 | fip->fcf_count--; |
221 | 250 | ||
222 | mutex_lock(&ctlr_dev->lock); | 251 | /* |
223 | 252 | * If ctlr_dev doesn't exist then it means we're a libfcoe user | |
224 | fcf_dev = fcoe_fcf_to_fcf_dev(new); | 253 | * who doesn't use fcoe_syfs and didn't allocate a fcoe_ctlr_device |
225 | WARN_ON(!fcf_dev); | 254 | * or a fcoe_fcf_device. |
226 | new->fcf_dev = NULL; | 255 | * |
227 | fcoe_fcf_device_delete(fcf_dev); | 256 | * fnic would be an example of a driver with this behavior. In this |
228 | kfree(new); | 257 | * case we want to remove the fcoe_fcf from the fcoe_ctlr list (above), |
229 | 258 | * but we don't want to make sysfs changes. | |
230 | mutex_unlock(&ctlr_dev->lock); | 259 | */ |
260 | cdev = fcoe_ctlr_to_ctlr_dev(fip); | ||
261 | if (cdev) { | ||
262 | mutex_lock(&cdev->lock); | ||
263 | fcf_dev = fcoe_fcf_to_fcf_dev(new); | ||
264 | WARN_ON(!fcf_dev); | ||
265 | new->fcf_dev = NULL; | ||
266 | fcoe_fcf_device_delete(fcf_dev); | ||
267 | kfree(new); | ||
268 | mutex_unlock(&cdev->lock); | ||
269 | } | ||
231 | } | 270 | } |
232 | 271 | ||
233 | /** | 272 | /** |
@@ -300,7 +339,7 @@ static void fcoe_ctlr_announce(struct fcoe_ctlr *fip) | |||
300 | spin_unlock_bh(&fip->ctlr_lock); | 339 | spin_unlock_bh(&fip->ctlr_lock); |
301 | sel = fip->sel_fcf; | 340 | sel = fip->sel_fcf; |
302 | 341 | ||
303 | if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr)) | 342 | if (sel && ether_addr_equal(sel->fcf_mac, fip->dest_addr)) |
304 | goto unlock; | 343 | goto unlock; |
305 | if (!is_zero_ether_addr(fip->dest_addr)) { | 344 | if (!is_zero_ether_addr(fip->dest_addr)) { |
306 | printk(KERN_NOTICE "libfcoe: host%d: " | 345 | printk(KERN_NOTICE "libfcoe: host%d: " |
@@ -1000,7 +1039,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
1000 | if (fcf->switch_name == new.switch_name && | 1039 | if (fcf->switch_name == new.switch_name && |
1001 | fcf->fabric_name == new.fabric_name && | 1040 | fcf->fabric_name == new.fabric_name && |
1002 | fcf->fc_map == new.fc_map && | 1041 | fcf->fc_map == new.fc_map && |
1003 | compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) { | 1042 | ether_addr_equal(fcf->fcf_mac, new.fcf_mac)) { |
1004 | found = 1; | 1043 | found = 1; |
1005 | break; | 1044 | break; |
1006 | } | 1045 | } |
@@ -1340,7 +1379,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
1340 | mp = (struct fip_mac_desc *)desc; | 1379 | mp = (struct fip_mac_desc *)desc; |
1341 | if (dlen < sizeof(*mp)) | 1380 | if (dlen < sizeof(*mp)) |
1342 | goto err; | 1381 | goto err; |
1343 | if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac)) | 1382 | if (!ether_addr_equal(mp->fd_mac, fcf->fcf_mac)) |
1344 | goto err; | 1383 | goto err; |
1345 | desc_mask &= ~BIT(FIP_DT_MAC); | 1384 | desc_mask &= ~BIT(FIP_DT_MAC); |
1346 | break; | 1385 | break; |
@@ -1418,8 +1457,8 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
1418 | * 'port_id' is already validated, check MAC address and | 1457 | * 'port_id' is already validated, check MAC address and |
1419 | * wwpn | 1458 | * wwpn |
1420 | */ | 1459 | */ |
1421 | if (compare_ether_addr(fip->get_src_addr(vn_port), | 1460 | if (!ether_addr_equal(fip->get_src_addr(vn_port), |
1422 | vp->fd_mac) != 0 || | 1461 | vp->fd_mac) || |
1423 | get_unaligned_be64(&vp->fd_wwpn) != | 1462 | get_unaligned_be64(&vp->fd_wwpn) != |
1424 | vn_port->wwpn) | 1463 | vn_port->wwpn) |
1425 | continue; | 1464 | continue; |
@@ -1453,6 +1492,9 @@ err: | |||
1453 | */ | 1492 | */ |
1454 | void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) | 1493 | void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) |
1455 | { | 1494 | { |
1495 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
1496 | if (!skb) | ||
1497 | return; | ||
1456 | skb_queue_tail(&fip->fip_recv_list, skb); | 1498 | skb_queue_tail(&fip->fip_recv_list, skb); |
1457 | schedule_work(&fip->recv_work); | 1499 | schedule_work(&fip->recv_work); |
1458 | } | 1500 | } |
@@ -1479,12 +1521,12 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
1479 | goto drop; | 1521 | goto drop; |
1480 | eh = eth_hdr(skb); | 1522 | eh = eth_hdr(skb); |
1481 | if (fip->mode == FIP_MODE_VN2VN) { | 1523 | if (fip->mode == FIP_MODE_VN2VN) { |
1482 | if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) && | 1524 | if (!ether_addr_equal(eh->h_dest, fip->ctl_src_addr) && |
1483 | compare_ether_addr(eh->h_dest, fcoe_all_vn2vn) && | 1525 | !ether_addr_equal(eh->h_dest, fcoe_all_vn2vn) && |
1484 | compare_ether_addr(eh->h_dest, fcoe_all_p2p)) | 1526 | !ether_addr_equal(eh->h_dest, fcoe_all_p2p)) |
1485 | goto drop; | 1527 | goto drop; |
1486 | } else if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) && | 1528 | } else if (!ether_addr_equal(eh->h_dest, fip->ctl_src_addr) && |
1487 | compare_ether_addr(eh->h_dest, fcoe_all_enode)) | 1529 | !ether_addr_equal(eh->h_dest, fcoe_all_enode)) |
1488 | goto drop; | 1530 | goto drop; |
1489 | fiph = (struct fip_header *)skb->data; | 1531 | fiph = (struct fip_header *)skb->data; |
1490 | op = ntohs(fiph->fip_op); | 1532 | op = ntohs(fiph->fip_op); |
@@ -1856,7 +1898,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, | |||
1856 | * address_mode flag to use FC_OUI-based Ethernet DA. | 1898 | * address_mode flag to use FC_OUI-based Ethernet DA. |
1857 | * Otherwise we use the FCoE gateway addr | 1899 | * Otherwise we use the FCoE gateway addr |
1858 | */ | 1900 | */ |
1859 | if (!compare_ether_addr(sa, (u8[6])FC_FCOE_FLOGI_MAC)) { | 1901 | if (ether_addr_equal(sa, (u8[6])FC_FCOE_FLOGI_MAC)) { |
1860 | fcoe_ctlr_map_dest(fip); | 1902 | fcoe_ctlr_map_dest(fip); |
1861 | } else { | 1903 | } else { |
1862 | memcpy(fip->dest_addr, sa, ETH_ALEN); | 1904 | memcpy(fip->dest_addr, sa, ETH_ALEN); |
@@ -2825,8 +2867,8 @@ unlock: | |||
2825 | * disabled, so that should ensure that this routine is only called | 2867 | * disabled, so that should ensure that this routine is only called |
2826 | * when nothing is happening. | 2868 | * when nothing is happening. |
2827 | */ | 2869 | */ |
2828 | void fcoe_ctlr_mode_set(struct fc_lport *lport, struct fcoe_ctlr *fip, | 2870 | static void fcoe_ctlr_mode_set(struct fc_lport *lport, struct fcoe_ctlr *fip, |
2829 | enum fip_state fip_mode) | 2871 | enum fip_state fip_mode) |
2830 | { | 2872 | { |
2831 | void *priv; | 2873 | void *priv; |
2832 | 2874 | ||