diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/scsi/fnic/fnic_scsi.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/scsi/fnic/fnic_scsi.c')
-rw-r--r-- | drivers/scsi/fnic/fnic_scsi.c | 97 |
1 files changed, 39 insertions, 58 deletions
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index bfc996971b81..3cc47c6e1ada 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/if_ether.h> | 26 | #include <linux/if_ether.h> |
27 | #include <linux/if_vlan.h> | 27 | #include <linux/if_vlan.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/gfp.h> | ||
29 | #include <scsi/scsi.h> | 30 | #include <scsi/scsi.h> |
30 | #include <scsi/scsi_host.h> | 31 | #include <scsi/scsi_host.h> |
31 | #include <scsi/scsi_device.h> | 32 | #include <scsi/scsi_device.h> |
@@ -174,6 +175,9 @@ int fnic_fw_reset_handler(struct fnic *fnic) | |||
174 | int ret = 0; | 175 | int ret = 0; |
175 | unsigned long flags; | 176 | unsigned long flags; |
176 | 177 | ||
178 | skb_queue_purge(&fnic->frame_queue); | ||
179 | skb_queue_purge(&fnic->tx_queue); | ||
180 | |||
177 | spin_lock_irqsave(&fnic->wq_copy_lock[0], flags); | 181 | spin_lock_irqsave(&fnic->wq_copy_lock[0], flags); |
178 | 182 | ||
179 | if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0]) | 183 | if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0]) |
@@ -200,9 +204,11 @@ int fnic_fw_reset_handler(struct fnic *fnic) | |||
200 | * fnic_flogi_reg_handler | 204 | * fnic_flogi_reg_handler |
201 | * Routine to send flogi register msg to fw | 205 | * Routine to send flogi register msg to fw |
202 | */ | 206 | */ |
203 | int fnic_flogi_reg_handler(struct fnic *fnic) | 207 | int fnic_flogi_reg_handler(struct fnic *fnic, u32 fc_id) |
204 | { | 208 | { |
205 | struct vnic_wq_copy *wq = &fnic->wq_copy[0]; | 209 | struct vnic_wq_copy *wq = &fnic->wq_copy[0]; |
210 | enum fcpio_flogi_reg_format_type format; | ||
211 | struct fc_lport *lp = fnic->lport; | ||
206 | u8 gw_mac[ETH_ALEN]; | 212 | u8 gw_mac[ETH_ALEN]; |
207 | int ret = 0; | 213 | int ret = 0; |
208 | unsigned long flags; | 214 | unsigned long flags; |
@@ -217,23 +223,32 @@ int fnic_flogi_reg_handler(struct fnic *fnic) | |||
217 | goto flogi_reg_ioreq_end; | 223 | goto flogi_reg_ioreq_end; |
218 | } | 224 | } |
219 | 225 | ||
220 | if (fnic->fcoui_mode) | 226 | if (fnic->ctlr.map_dest) { |
221 | memset(gw_mac, 0xff, ETH_ALEN); | 227 | memset(gw_mac, 0xff, ETH_ALEN); |
222 | else | 228 | format = FCPIO_FLOGI_REG_DEF_DEST; |
223 | memcpy(gw_mac, fnic->dest_addr, ETH_ALEN); | 229 | } else { |
230 | memcpy(gw_mac, fnic->ctlr.dest_addr, ETH_ALEN); | ||
231 | format = FCPIO_FLOGI_REG_GW_DEST; | ||
232 | } | ||
224 | 233 | ||
225 | fnic_queue_wq_copy_desc_flogi_reg(wq, SCSI_NO_TAG, | 234 | if ((fnic->config.flags & VFCF_FIP_CAPABLE) && !fnic->ctlr.map_dest) { |
226 | FCPIO_FLOGI_REG_GW_DEST, | 235 | fnic_queue_wq_copy_desc_fip_reg(wq, SCSI_NO_TAG, |
227 | fnic->s_id, | 236 | fc_id, gw_mac, |
228 | gw_mac); | 237 | fnic->data_src_addr, |
238 | lp->r_a_tov, lp->e_d_tov); | ||
239 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | ||
240 | "FLOGI FIP reg issued fcid %x src %pM dest %pM\n", | ||
241 | fc_id, fnic->data_src_addr, gw_mac); | ||
242 | } else { | ||
243 | fnic_queue_wq_copy_desc_flogi_reg(wq, SCSI_NO_TAG, | ||
244 | format, fc_id, gw_mac); | ||
245 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | ||
246 | "FLOGI reg issued fcid %x map %d dest %pM\n", | ||
247 | fc_id, fnic->ctlr.map_dest, gw_mac); | ||
248 | } | ||
229 | 249 | ||
230 | flogi_reg_ioreq_end: | 250 | flogi_reg_ioreq_end: |
231 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); | 251 | 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; | 252 | return ret; |
238 | } | 253 | } |
239 | 254 | ||
@@ -319,7 +334,8 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, | |||
319 | 0, /* scsi cmd ref, always 0 */ | 334 | 0, /* scsi cmd ref, always 0 */ |
320 | pri_tag, /* scsi pri and tag */ | 335 | pri_tag, /* scsi pri and tag */ |
321 | flags, /* command flags */ | 336 | flags, /* command flags */ |
322 | sc->cmnd, scsi_bufflen(sc), | 337 | sc->cmnd, sc->cmd_len, |
338 | scsi_bufflen(sc), | ||
323 | fc_lun.scsi_lun, io_req->port_id, | 339 | fc_lun.scsi_lun, io_req->port_id, |
324 | rport->maxframe_size, rp->r_a_tov, | 340 | rport->maxframe_size, rp->r_a_tov, |
325 | rp->e_d_tov); | 341 | rp->e_d_tov); |
@@ -452,7 +468,6 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic, | |||
452 | u8 hdr_status; | 468 | u8 hdr_status; |
453 | struct fcpio_tag tag; | 469 | struct fcpio_tag tag; |
454 | int ret = 0; | 470 | int ret = 0; |
455 | struct fc_frame *flogi; | ||
456 | unsigned long flags; | 471 | unsigned long flags; |
457 | 472 | ||
458 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); | 473 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); |
@@ -462,9 +477,6 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic, | |||
462 | 477 | ||
463 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 478 | spin_lock_irqsave(&fnic->fnic_lock, flags); |
464 | 479 | ||
465 | flogi = fnic->flogi; | ||
466 | fnic->flogi = NULL; | ||
467 | |||
468 | /* fnic should be in FC_TRANS_ETH_MODE */ | 480 | /* fnic should be in FC_TRANS_ETH_MODE */ |
469 | if (fnic->state == FNIC_IN_FC_TRANS_ETH_MODE) { | 481 | if (fnic->state == FNIC_IN_FC_TRANS_ETH_MODE) { |
470 | /* Check status of reset completion */ | 482 | /* Check status of reset completion */ |
@@ -505,17 +517,14 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic, | |||
505 | * free the flogi frame. Else, send it out | 517 | * free the flogi frame. Else, send it out |
506 | */ | 518 | */ |
507 | if (fnic->remove_wait || ret) { | 519 | if (fnic->remove_wait || ret) { |
508 | fnic->flogi_oxid = FC_XID_UNKNOWN; | ||
509 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 520 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
510 | if (flogi) | 521 | skb_queue_purge(&fnic->tx_queue); |
511 | dev_kfree_skb_irq(fp_skb(flogi)); | ||
512 | goto reset_cmpl_handler_end; | 522 | goto reset_cmpl_handler_end; |
513 | } | 523 | } |
514 | 524 | ||
515 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 525 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
516 | 526 | ||
517 | if (flogi) | 527 | fnic_flush_tx(fnic); |
518 | ret = fnic_send_frame(fnic, flogi); | ||
519 | 528 | ||
520 | reset_cmpl_handler_end: | 529 | reset_cmpl_handler_end: |
521 | return ret; | 530 | return ret; |
@@ -532,18 +541,13 @@ static int fnic_fcpio_flogi_reg_cmpl_handler(struct fnic *fnic, | |||
532 | u8 hdr_status; | 541 | u8 hdr_status; |
533 | struct fcpio_tag tag; | 542 | struct fcpio_tag tag; |
534 | int ret = 0; | 543 | int ret = 0; |
535 | struct fc_frame *flogi_resp = NULL; | ||
536 | unsigned long flags; | 544 | unsigned long flags; |
537 | struct sk_buff *skb; | ||
538 | 545 | ||
539 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); | 546 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); |
540 | 547 | ||
541 | /* Update fnic state based on status of flogi reg completion */ | 548 | /* Update fnic state based on status of flogi reg completion */ |
542 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 549 | spin_lock_irqsave(&fnic->fnic_lock, flags); |
543 | 550 | ||
544 | flogi_resp = fnic->flogi_resp; | ||
545 | fnic->flogi_resp = NULL; | ||
546 | |||
547 | if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE) { | 551 | if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE) { |
548 | 552 | ||
549 | /* Check flogi registration completion status */ | 553 | /* Check flogi registration completion status */ |
@@ -567,25 +571,17 @@ static int fnic_fcpio_flogi_reg_cmpl_handler(struct fnic *fnic, | |||
567 | ret = -1; | 571 | ret = -1; |
568 | } | 572 | } |
569 | 573 | ||
570 | /* Successful flogi reg cmpl, pass frame to LibFC */ | 574 | if (!ret) { |
571 | if (!ret && flogi_resp) { | ||
572 | if (fnic->stop_rx_link_events) { | 575 | if (fnic->stop_rx_link_events) { |
573 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 576 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
574 | goto reg_cmpl_handler_end; | 577 | goto reg_cmpl_handler_end; |
575 | } | 578 | } |
576 | skb = (struct sk_buff *)flogi_resp; | ||
577 | /* Use fr_flags to indicate whether flogi resp or not */ | ||
578 | fr_flags(flogi_resp) = 1; | ||
579 | fr_dev(flogi_resp) = fnic->lport; | ||
580 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 579 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
581 | 580 | ||
582 | skb_queue_tail(&fnic->frame_queue, skb); | 581 | fnic_flush_tx(fnic); |
583 | queue_work(fnic_event_queue, &fnic->frame_work); | 582 | queue_work(fnic_event_queue, &fnic->frame_work); |
584 | |||
585 | } else { | 583 | } else { |
586 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 584 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
587 | if (flogi_resp) | ||
588 | dev_kfree_skb_irq(fp_skb(flogi_resp)); | ||
589 | } | 585 | } |
590 | 586 | ||
591 | reg_cmpl_handler_end: | 587 | reg_cmpl_handler_end: |
@@ -907,6 +903,7 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev, | |||
907 | break; | 903 | break; |
908 | 904 | ||
909 | case FCPIO_FLOGI_REG_CMPL: /* fw completed flogi_reg */ | 905 | case FCPIO_FLOGI_REG_CMPL: /* fw completed flogi_reg */ |
906 | case FCPIO_FLOGI_FIP_REG_CMPL: /* fw completed flogi_fip_reg */ | ||
910 | ret = fnic_fcpio_flogi_reg_cmpl_handler(fnic, desc); | 907 | ret = fnic_fcpio_flogi_reg_cmpl_handler(fnic, desc); |
911 | break; | 908 | break; |
912 | 909 | ||
@@ -1224,22 +1221,6 @@ void fnic_terminate_rport_io(struct fc_rport *rport) | |||
1224 | 1221 | ||
1225 | } | 1222 | } |
1226 | 1223 | ||
1227 | static void fnic_block_error_handler(struct scsi_cmnd *sc) | ||
1228 | { | ||
1229 | struct Scsi_Host *shost = sc->device->host; | ||
1230 | struct fc_rport *rport = starget_to_rport(scsi_target(sc->device)); | ||
1231 | unsigned long flags; | ||
1232 | |||
1233 | spin_lock_irqsave(shost->host_lock, flags); | ||
1234 | while (rport->port_state == FC_PORTSTATE_BLOCKED) { | ||
1235 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1236 | msleep(1000); | ||
1237 | spin_lock_irqsave(shost->host_lock, flags); | ||
1238 | } | ||
1239 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1240 | |||
1241 | } | ||
1242 | |||
1243 | /* | 1224 | /* |
1244 | * This function is exported to SCSI for sending abort cmnds. | 1225 | * This function is exported to SCSI for sending abort cmnds. |
1245 | * A SCSI IO is represented by a io_req in the driver. | 1226 | * A SCSI IO is represented by a io_req in the driver. |
@@ -1259,7 +1240,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) | |||
1259 | DECLARE_COMPLETION_ONSTACK(tm_done); | 1240 | DECLARE_COMPLETION_ONSTACK(tm_done); |
1260 | 1241 | ||
1261 | /* Wait for rport to unblock */ | 1242 | /* Wait for rport to unblock */ |
1262 | fnic_block_error_handler(sc); | 1243 | fc_block_scsi_eh(sc); |
1263 | 1244 | ||
1264 | /* Get local-port, check ready and link up */ | 1245 | /* Get local-port, check ready and link up */ |
1265 | lp = shost_priv(sc->device->host); | 1246 | lp = shost_priv(sc->device->host); |
@@ -1541,7 +1522,7 @@ int fnic_device_reset(struct scsi_cmnd *sc) | |||
1541 | DECLARE_COMPLETION_ONSTACK(tm_done); | 1522 | DECLARE_COMPLETION_ONSTACK(tm_done); |
1542 | 1523 | ||
1543 | /* Wait for rport to unblock */ | 1524 | /* Wait for rport to unblock */ |
1544 | fnic_block_error_handler(sc); | 1525 | fc_block_scsi_eh(sc); |
1545 | 1526 | ||
1546 | /* Get local-port, check ready and link up */ | 1527 | /* Get local-port, check ready and link up */ |
1547 | lp = shost_priv(sc->device->host); | 1528 | lp = shost_priv(sc->device->host); |
@@ -1762,7 +1743,7 @@ void fnic_scsi_abort_io(struct fc_lport *lp) | |||
1762 | fnic->remove_wait = &remove_wait; | 1743 | fnic->remove_wait = &remove_wait; |
1763 | old_state = fnic->state; | 1744 | old_state = fnic->state; |
1764 | fnic->state = FNIC_IN_FC_TRANS_ETH_MODE; | 1745 | fnic->state = FNIC_IN_FC_TRANS_ETH_MODE; |
1765 | vnic_dev_del_addr(fnic->vdev, fnic->data_src_addr); | 1746 | fnic_update_mac_locked(fnic, fnic->ctlr.ctl_src_addr); |
1766 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 1747 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
1767 | 1748 | ||
1768 | err = fnic_fw_reset_handler(fnic); | 1749 | err = fnic_fw_reset_handler(fnic); |
@@ -1802,7 +1783,7 @@ void fnic_scsi_cleanup(struct fc_lport *lp) | |||
1802 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 1783 | spin_lock_irqsave(&fnic->fnic_lock, flags); |
1803 | old_state = fnic->state; | 1784 | old_state = fnic->state; |
1804 | fnic->state = FNIC_IN_FC_TRANS_ETH_MODE; | 1785 | fnic->state = FNIC_IN_FC_TRANS_ETH_MODE; |
1805 | vnic_dev_del_addr(fnic->vdev, fnic->data_src_addr); | 1786 | fnic_update_mac_locked(fnic, fnic->ctlr.ctl_src_addr); |
1806 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 1787 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
1807 | 1788 | ||
1808 | if (fnic_fw_reset_handler(fnic)) { | 1789 | if (fnic_fw_reset_handler(fnic)) { |