diff options
author | Chris Leech <christopher.leech@intel.com> | 2009-08-25 17:00:02 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-09-10 13:07:35 -0400 |
commit | 030f4e001f13e0ee80bac1e756013341b1674d10 (patch) | |
tree | 042791ba7bc3d9f2543abf33c511034421c97178 /drivers/scsi/fcoe/fcoe.c | |
parent | cb0a6ca81439a9f113d3b46de0953da168a06f6a (diff) |
[SCSI] fcoe: fcoe_interface create, destroy and refcounting
Up to this point the fcoe_instance structure was simply kzalloc/kfreed. This
patch introduces create and destroy functions as well as kref based reference
counting. The create function will grow as the initialization code is moved
there.
Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 97 |
1 files changed, 78 insertions, 19 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 7f14c633da6f..d1d6b3b8bf5b 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -139,6 +139,58 @@ static struct scsi_host_template fcoe_shost_template = { | |||
139 | }; | 139 | }; |
140 | 140 | ||
141 | /** | 141 | /** |
142 | * fcoe_interface_create() | ||
143 | * @netdev: network interface | ||
144 | * | ||
145 | * Returns: pointer to a struct fcoe_interface or NULL on error | ||
146 | */ | ||
147 | static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) | ||
148 | { | ||
149 | struct fcoe_interface *fcoe; | ||
150 | |||
151 | fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL); | ||
152 | if (!fcoe) { | ||
153 | FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n"); | ||
154 | return NULL; | ||
155 | } | ||
156 | |||
157 | kref_init(&fcoe->kref); | ||
158 | fcoe->netdev = netdev; | ||
159 | |||
160 | return fcoe; | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * fcoe_interface_release() - fcoe_port kref release function | ||
165 | * @kref: embedded reference count in an fcoe_interface struct | ||
166 | */ | ||
167 | static void fcoe_interface_release(struct kref *kref) | ||
168 | { | ||
169 | struct fcoe_interface *fcoe; | ||
170 | |||
171 | fcoe = container_of(kref, struct fcoe_interface, kref); | ||
172 | kfree(fcoe); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * fcoe_interface_get() | ||
177 | * @fcoe: | ||
178 | */ | ||
179 | static inline void fcoe_interface_get(struct fcoe_interface *fcoe) | ||
180 | { | ||
181 | kref_get(&fcoe->kref); | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * fcoe_interface_put() | ||
186 | * @fcoe: | ||
187 | */ | ||
188 | static inline void fcoe_interface_put(struct fcoe_interface *fcoe) | ||
189 | { | ||
190 | kref_put(&fcoe->kref, fcoe_interface_release); | ||
191 | } | ||
192 | |||
193 | /** | ||
142 | * fcoe_fip_recv - handle a received FIP frame. | 194 | * fcoe_fip_recv - handle a received FIP frame. |
143 | * @skb: the receive skb | 195 | * @skb: the receive skb |
144 | * @dev: associated &net_device | 196 | * @dev: associated &net_device |
@@ -558,7 +610,7 @@ static void fcoe_if_destroy(struct fc_lport *lport) | |||
558 | /* Release the net_device and Scsi_Host */ | 610 | /* Release the net_device and Scsi_Host */ |
559 | dev_put(netdev); | 611 | dev_put(netdev); |
560 | scsi_host_put(lport->host); | 612 | scsi_host_put(lport->host); |
561 | kfree(fcoe); /* TODO, should be refcounted */ | 613 | fcoe_interface_put(fcoe); |
562 | } | 614 | } |
563 | 615 | ||
564 | /* | 616 | /* |
@@ -604,8 +656,8 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = { | |||
604 | }; | 656 | }; |
605 | 657 | ||
606 | /** | 658 | /** |
607 | * fcoe_if_create() - this function creates the fcoe interface | 659 | * fcoe_if_create() - this function creates the fcoe port |
608 | * @netdev: pointer the associated netdevice | 660 | * @fcoe: fcoe_interface structure to create an fc_lport instance on |
609 | * @parent: device pointer to be the parent in sysfs for the SCSI host | 661 | * @parent: device pointer to be the parent in sysfs for the SCSI host |
610 | * | 662 | * |
611 | * Creates fc_lport struct and scsi_host for lport, configures lport | 663 | * Creates fc_lport struct and scsi_host for lport, configures lport |
@@ -613,30 +665,23 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = { | |||
613 | * | 665 | * |
614 | * Returns : The allocated fc_lport or an error pointer | 666 | * Returns : The allocated fc_lport or an error pointer |
615 | */ | 667 | */ |
616 | static struct fc_lport *fcoe_if_create(struct net_device *netdev, | 668 | static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, |
617 | struct device *parent) | 669 | struct device *parent) |
618 | { | 670 | { |
619 | int rc; | 671 | int rc; |
620 | struct fc_lport *lport = NULL; | 672 | struct fc_lport *lport = NULL; |
621 | struct fcoe_port *port; | 673 | struct fcoe_port *port; |
622 | struct fcoe_interface *fcoe; | ||
623 | struct Scsi_Host *shost; | 674 | struct Scsi_Host *shost; |
675 | struct net_device *netdev = fcoe->netdev; | ||
624 | 676 | ||
625 | FCOE_NETDEV_DBG(netdev, "Create Interface\n"); | 677 | FCOE_NETDEV_DBG(netdev, "Create Interface\n"); |
626 | 678 | ||
627 | fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL); | ||
628 | if (!fcoe) { | ||
629 | FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n"); | ||
630 | rc = -ENOMEM; | ||
631 | goto out; | ||
632 | } | ||
633 | |||
634 | shost = libfc_host_alloc(&fcoe_shost_template, | 679 | shost = libfc_host_alloc(&fcoe_shost_template, |
635 | sizeof(struct fcoe_port)); | 680 | sizeof(struct fcoe_port)); |
636 | if (!shost) { | 681 | if (!shost) { |
637 | FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n"); | 682 | FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n"); |
638 | rc = -ENOMEM; | 683 | rc = -ENOMEM; |
639 | goto out_kfree_port; | 684 | goto out; |
640 | } | 685 | } |
641 | lport = shost_priv(shost); | 686 | lport = shost_priv(shost); |
642 | port = lport_priv(lport); | 687 | port = lport_priv(lport); |
@@ -708,7 +753,7 @@ static struct fc_lport *fcoe_if_create(struct net_device *netdev, | |||
708 | fcoe_ctlr_link_up(&fcoe->ctlr); | 753 | fcoe_ctlr_link_up(&fcoe->ctlr); |
709 | 754 | ||
710 | dev_hold(netdev); | 755 | dev_hold(netdev); |
711 | 756 | fcoe_interface_get(fcoe); | |
712 | return lport; | 757 | return lport; |
713 | 758 | ||
714 | out_lp_destroy: | 759 | out_lp_destroy: |
@@ -717,8 +762,6 @@ out_netdev_cleanup: | |||
717 | fcoe_netdev_cleanup(port); | 762 | fcoe_netdev_cleanup(port); |
718 | out_host_put: | 763 | out_host_put: |
719 | scsi_host_put(lport->host); | 764 | scsi_host_put(lport->host); |
720 | out_kfree_port: | ||
721 | kfree(fcoe); | ||
722 | out: | 765 | out: |
723 | return ERR_PTR(rc); | 766 | return ERR_PTR(rc); |
724 | } | 767 | } |
@@ -1620,6 +1663,8 @@ static int fcoe_ethdrv_put(const struct net_device *netdev) | |||
1620 | static int fcoe_destroy(const char *buffer, struct kernel_param *kp) | 1663 | static int fcoe_destroy(const char *buffer, struct kernel_param *kp) |
1621 | { | 1664 | { |
1622 | struct net_device *netdev; | 1665 | struct net_device *netdev; |
1666 | struct fcoe_interface *fcoe; | ||
1667 | struct fcoe_port *port; | ||
1623 | struct fc_lport *lport; | 1668 | struct fc_lport *lport; |
1624 | int rc; | 1669 | int rc; |
1625 | 1670 | ||
@@ -1634,6 +1679,8 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) | |||
1634 | rc = -ENODEV; | 1679 | rc = -ENODEV; |
1635 | goto out_putdev; | 1680 | goto out_putdev; |
1636 | } | 1681 | } |
1682 | port = lport_priv(lport); | ||
1683 | fcoe = port->fcoe; | ||
1637 | fcoe_if_destroy(lport); | 1684 | fcoe_if_destroy(lport); |
1638 | fcoe_ethdrv_put(netdev); | 1685 | fcoe_ethdrv_put(netdev); |
1639 | rc = 0; | 1686 | rc = 0; |
@@ -1653,6 +1700,7 @@ out_nodev: | |||
1653 | static int fcoe_create(const char *buffer, struct kernel_param *kp) | 1700 | static int fcoe_create(const char *buffer, struct kernel_param *kp) |
1654 | { | 1701 | { |
1655 | int rc; | 1702 | int rc; |
1703 | struct fcoe_interface *fcoe; | ||
1656 | struct fc_lport *lport; | 1704 | struct fc_lport *lport; |
1657 | struct net_device *netdev; | 1705 | struct net_device *netdev; |
1658 | 1706 | ||
@@ -1668,15 +1716,26 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) | |||
1668 | } | 1716 | } |
1669 | fcoe_ethdrv_get(netdev); | 1717 | fcoe_ethdrv_get(netdev); |
1670 | 1718 | ||
1671 | lport = fcoe_if_create(netdev, &netdev->dev); | 1719 | fcoe = fcoe_interface_create(netdev); |
1720 | if (!fcoe) { | ||
1721 | rc = -ENOMEM; | ||
1722 | goto out_putdev; | ||
1723 | } | ||
1724 | |||
1725 | lport = fcoe_if_create(fcoe, &netdev->dev); | ||
1672 | if (IS_ERR(lport)) { | 1726 | if (IS_ERR(lport)) { |
1673 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", | 1727 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", |
1674 | netdev->name); | 1728 | netdev->name); |
1675 | fcoe_ethdrv_put(netdev); | 1729 | fcoe_ethdrv_put(netdev); |
1676 | rc = -EIO; | 1730 | rc = -EIO; |
1677 | goto out_putdev; | 1731 | goto out_free; |
1678 | } | 1732 | } |
1679 | rc = 0; | 1733 | |
1734 | dev_put(netdev); | ||
1735 | return 0; | ||
1736 | |||
1737 | out_free: | ||
1738 | fcoe_interface_put(fcoe); | ||
1680 | out_putdev: | 1739 | out_putdev: |
1681 | dev_put(netdev); | 1740 | dev_put(netdev); |
1682 | out_nodev: | 1741 | out_nodev: |