Browse Source

[fc] Send xfer_window_changed() when FCP link is established

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
5f608a44a5
3 changed files with 100 additions and 13 deletions
  1. 44
    0
      src/include/ipxe/fc.h
  2. 32
    12
      src/net/fc.c
  3. 24
    1
      src/net/fcp.c

+ 44
- 0
src/include/ipxe/fc.h View File

455
 	struct fc_ulp *ulp;
455
 	struct fc_ulp *ulp;
456
 	/** List of users */
456
 	/** List of users */
457
 	struct list_head list;
457
 	struct list_head list;
458
+	/** Containing object reference count, or NULL */
459
+	struct refcnt *refcnt;
460
+	/** Examine link state
461
+	 *
462
+	 * @v user		Fibre Channel upper-layer-protocol user
463
+	 */
464
+	void ( * examine ) ( struct fc_ulp_user *user );
458
 };
465
 };
459
 
466
 
460
 /**
467
 /**
479
 	ref_put ( &ulp->refcnt );
486
 	ref_put ( &ulp->refcnt );
480
 }
487
 }
481
 
488
 
489
+/**
490
+ * Get reference to Fibre Channel upper-layer protocol user
491
+ *
492
+ * @v user		Fibre Channel upper-layer protocol user
493
+ * @ret user		Fibre Channel upper-layer protocol user
494
+ */
495
+static inline __attribute__ (( always_inline )) struct fc_ulp_user *
496
+fc_ulp_user_get ( struct fc_ulp_user *user ) {
497
+	ref_get ( user->refcnt );
498
+	return user;
499
+}
500
+
501
+/**
502
+ * Drop reference to Fibre Channel upper-layer protocol user
503
+ *
504
+ * @v user		Fibre Channel upper-layer protocol user
505
+ */
506
+static inline __attribute__ (( always_inline )) void
507
+fc_ulp_user_put ( struct fc_ulp_user *user ) {
508
+	ref_put ( user->refcnt );
509
+}
510
+
511
+/**
512
+ * Initialise Fibre Channel upper-layer protocol user
513
+ *
514
+ * @v user		Fibre Channel upper-layer protocol user
515
+ * @v examine		Examine link state method
516
+ * @v refcnt		Containing object reference count, or NULL
517
+ */
518
+static inline __attribute__ (( always_inline )) void
519
+fc_ulp_user_init ( struct fc_ulp_user *user,
520
+		   void ( * examine ) ( struct fc_ulp_user *user ),
521
+		   struct refcnt *refcnt ) {
522
+	user->examine = examine;
523
+	user->refcnt = refcnt;
524
+}
525
+
482
 extern struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *port_wwn,
526
 extern struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *port_wwn,
483
 					     unsigned int type );
527
 					     unsigned int type );
484
 extern struct fc_ulp *
528
 extern struct fc_ulp *

+ 32
- 12
src/net/fc.c View File

1651
  */
1651
  */
1652
 int fc_ulp_login ( struct fc_ulp *ulp, const void *param, size_t param_len,
1652
 int fc_ulp_login ( struct fc_ulp *ulp, const void *param, size_t param_len,
1653
 		   int originated ) {
1653
 		   int originated ) {
1654
+	struct fc_ulp_user *user;
1655
+	struct fc_ulp_user *tmp;
1654
 
1656
 
1655
 	/* Perform implicit logout if logged in and service parameters differ */
1657
 	/* Perform implicit logout if logged in and service parameters differ */
1656
 	if ( fc_link_ok ( &ulp->link ) &&
1658
 	if ( fc_link_ok ( &ulp->link ) &&
1659
 		fc_ulp_logout ( ulp, 0 );
1661
 		fc_ulp_logout ( ulp, 0 );
1660
 	}
1662
 	}
1661
 
1663
 
1664
+	/* Work around a bug in some versions of the Linux Fibre
1665
+	 * Channel stack, which fail to fully initialise image pairs
1666
+	 * established via a PRLI originated by the Linux stack
1667
+	 * itself.
1668
+	 */
1669
+	if ( originated )
1670
+		ulp->flags |= FC_ULP_ORIGINATED_LOGIN_OK;
1671
+	if ( ! ( ulp->flags & FC_ULP_ORIGINATED_LOGIN_OK ) ) {
1672
+		DBGC ( ulp, "FCULP %s/%02x sending extra PRLI to work around "
1673
+		       "Linux bug\n",
1674
+		       fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
1675
+		fc_link_stop ( &ulp->link );
1676
+		fc_link_start ( &ulp->link );
1677
+		return 0;
1678
+	}
1679
+
1662
 	/* Log in, if applicable */
1680
 	/* Log in, if applicable */
1663
 	if ( ! fc_link_ok ( &ulp->link ) ) {
1681
 	if ( ! fc_link_ok ( &ulp->link ) ) {
1664
 
1682
 
1685
 	/* Record login */
1703
 	/* Record login */
1686
 	fc_link_up ( &ulp->link );
1704
 	fc_link_up ( &ulp->link );
1687
 
1705
 
1688
-	/* Work around a bug in some versions of the Linux Fibre
1689
-	 * Channel stack, which fail to fully initialise image pairs
1690
-	 * established via a PRLI originated by the Linux stack
1691
-	 * itself.
1692
-	 */
1693
-	if ( originated )
1694
-		ulp->flags |= FC_ULP_ORIGINATED_LOGIN_OK;
1695
-	if ( ! ( ulp->flags & FC_ULP_ORIGINATED_LOGIN_OK ) ) {
1696
-		DBGC ( ulp, "FCULP %s/%02x sending extra PRLI to work around "
1697
-		       "Linux bug\n",
1698
-		       fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
1699
-		fc_link_start ( &ulp->link );
1706
+	/* Notify users of link state change */
1707
+	list_for_each_entry_safe ( user, tmp, &ulp->users, list ) {
1708
+		fc_ulp_user_get ( user );
1709
+		user->examine ( user );
1710
+		fc_ulp_user_put ( user );
1700
 	}
1711
 	}
1701
 
1712
 
1702
 	return 0;
1713
 	return 0;
1709
  * @v rc		Reason for logout
1720
  * @v rc		Reason for logout
1710
  */
1721
  */
1711
 void fc_ulp_logout ( struct fc_ulp *ulp, int rc ) {
1722
 void fc_ulp_logout ( struct fc_ulp *ulp, int rc ) {
1723
+	struct fc_ulp_user *user;
1724
+	struct fc_ulp_user *tmp;
1712
 
1725
 
1713
 	DBGC ( ulp, "FCULP %s/%02x logged out: %s\n",
1726
 	DBGC ( ulp, "FCULP %s/%02x logged out: %s\n",
1714
 	       fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
1727
 	       fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
1726
 	/* Record logout */
1739
 	/* Record logout */
1727
 	fc_link_err ( &ulp->link, rc );
1740
 	fc_link_err ( &ulp->link, rc );
1728
 
1741
 
1742
+	/* Notify users of link state change */
1743
+	list_for_each_entry_safe ( user, tmp, &ulp->users, list ) {
1744
+		fc_ulp_user_get ( user );
1745
+		user->examine ( user );
1746
+		fc_ulp_user_put ( user );
1747
+	}
1748
+
1729
 	/* Close ULP if there are no clients attached */
1749
 	/* Close ULP if there are no clients attached */
1730
 	if ( list_empty ( &ulp->users ) )
1750
 	if ( list_empty ( &ulp->users ) )
1731
 		fc_ulp_close ( ulp, rc );
1751
 		fc_ulp_close ( ulp, rc );

+ 24
- 1
src/net/fcp.c View File

920
 static struct interface_descriptor fcpdev_scsi_desc =
920
 static struct interface_descriptor fcpdev_scsi_desc =
921
 	INTF_DESC ( struct fcp_device, scsi, fcpdev_scsi_op );
921
 	INTF_DESC ( struct fcp_device, scsi, fcpdev_scsi_op );
922
 
922
 
923
+/**
924
+ * Examine FCP ULP link state
925
+ *
926
+ * @v user		Fibre Channel upper-layer protocol user
927
+ */
928
+static void fcpdev_examine ( struct fc_ulp_user *user ) {
929
+	struct fcp_device *fcpdev =
930
+		container_of ( user, struct fcp_device, user );
931
+
932
+	if ( fc_link_ok ( &fcpdev->user.ulp->link ) ) {
933
+		DBGC ( fcpdev, "FCP %p link is up\n", fcpdev );
934
+	} else {
935
+		DBGC ( fcpdev, "FCP %p link is down: %s\n",
936
+		       fcpdev, strerror ( fcpdev->user.ulp->link.rc ) );
937
+	}
938
+
939
+	/* Notify SCSI layer of window change */
940
+	xfer_window_changed ( &fcpdev->scsi );
941
+}
942
+
923
 /**
943
 /**
924
  * Open FCP device
944
  * Open FCP device
925
  *
945
  *
950
 	ref_init ( &fcpdev->refcnt, NULL );
970
 	ref_init ( &fcpdev->refcnt, NULL );
951
 	intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt );
971
 	intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt );
952
 	INIT_LIST_HEAD ( &fcpdev->fcpcmds );
972
 	INIT_LIST_HEAD ( &fcpdev->fcpcmds );
953
-	fc_ulp_attach ( ulp, &fcpdev->user );
973
+	fc_ulp_user_init ( &fcpdev->user, fcpdev_examine, &fcpdev->refcnt );
954
 
974
 
955
 	DBGC ( fcpdev, "FCP %p opened for %s\n", fcpdev, fc_ntoa ( wwn ) );
975
 	DBGC ( fcpdev, "FCP %p opened for %s\n", fcpdev, fc_ntoa ( wwn ) );
956
 
976
 
977
+	/* Attach to Fibre Channel ULP */
978
+	fc_ulp_attach ( ulp, &fcpdev->user );
979
+
957
 	/* Preserve parameters required for boot firmware table */
980
 	/* Preserve parameters required for boot firmware table */
958
 	memcpy ( &fcpdev->wwn, wwn, sizeof ( fcpdev->wwn ) );
981
 	memcpy ( &fcpdev->wwn, wwn, sizeof ( fcpdev->wwn ) );
959
 	memcpy ( &fcpdev->lun, lun, sizeof ( fcpdev->lun ) );
982
 	memcpy ( &fcpdev->lun, lun, sizeof ( fcpdev->lun ) );

Loading…
Cancel
Save