Explorar el Código

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

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown hace 13 años
padre
commit
5f608a44a5
Se han modificado 3 ficheros con 100 adiciones y 13 borrados
  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 Ver fichero

@@ -455,6 +455,13 @@ struct fc_ulp_user {
455 455
 	struct fc_ulp *ulp;
456 456
 	/** List of users */
457 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,6 +486,43 @@ fc_ulp_put ( struct fc_ulp *ulp ) {
479 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 526
 extern struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *port_wwn,
483 527
 					     unsigned int type );
484 528
 extern struct fc_ulp *

+ 32
- 12
src/net/fc.c Ver fichero

@@ -1651,6 +1651,8 @@ void fc_ulp_detach ( struct fc_ulp_user *user ) {
1651 1651
  */
1652 1652
 int fc_ulp_login ( struct fc_ulp *ulp, const void *param, size_t param_len,
1653 1653
 		   int originated ) {
1654
+	struct fc_ulp_user *user;
1655
+	struct fc_ulp_user *tmp;
1654 1656
 
1655 1657
 	/* Perform implicit logout if logged in and service parameters differ */
1656 1658
 	if ( fc_link_ok ( &ulp->link ) &&
@@ -1659,6 +1661,22 @@ int fc_ulp_login ( struct fc_ulp *ulp, const void *param, size_t param_len,
1659 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 1680
 	/* Log in, if applicable */
1663 1681
 	if ( ! fc_link_ok ( &ulp->link ) ) {
1664 1682
 
@@ -1685,18 +1703,11 @@ int fc_ulp_login ( struct fc_ulp *ulp, const void *param, size_t param_len,
1685 1703
 	/* Record login */
1686 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 1713
 	return 0;
@@ -1709,6 +1720,8 @@ int fc_ulp_login ( struct fc_ulp *ulp, const void *param, size_t param_len,
1709 1720
  * @v rc		Reason for logout
1710 1721
  */
1711 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 1726
 	DBGC ( ulp, "FCULP %s/%02x logged out: %s\n",
1714 1727
 	       fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
@@ -1726,6 +1739,13 @@ void fc_ulp_logout ( struct fc_ulp *ulp, int rc ) {
1726 1739
 	/* Record logout */
1727 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 1749
 	/* Close ULP if there are no clients attached */
1730 1750
 	if ( list_empty ( &ulp->users ) )
1731 1751
 		fc_ulp_close ( ulp, rc );

+ 24
- 1
src/net/fcp.c Ver fichero

@@ -920,6 +920,26 @@ static struct interface_operation fcpdev_scsi_op[] = {
920 920
 static struct interface_descriptor fcpdev_scsi_desc =
921 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 944
  * Open FCP device
925 945
  *
@@ -950,10 +970,13 @@ static int fcpdev_open ( struct interface *parent, struct fc_name *wwn,
950 970
 	ref_init ( &fcpdev->refcnt, NULL );
951 971
 	intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt );
952 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 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 980
 	/* Preserve parameters required for boot firmware table */
958 981
 	memcpy ( &fcpdev->wwn, wwn, sizeof ( fcpdev->wwn ) );
959 982
 	memcpy ( &fcpdev->lun, lun, sizeof ( fcpdev->lun ) );

Loading…
Cancelar
Guardar