All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eddie James <eajames@linux.vnet.ibm.com>
To: openbmc@lists.ozlabs.org
Cc: joel@jms.id.au, cbostic@linux.vnet.ibm.com,
	"Edward A. James" <eajames@us.ibm.com>
Subject: [PATCH linux dev-4.7 v2 1/2] drivers: fsi: i2c fix probing
Date: Fri, 10 Feb 2017 10:49:21 -0600	[thread overview]
Message-ID: <1486745362-7790-2-git-send-email-eajames@linux.vnet.ibm.com> (raw)
In-Reply-To: <1486745362-7790-1-git-send-email-eajames@linux.vnet.ibm.com>

From: "Edward A. James" <eajames@us.ibm.com>

resolve the problems when probing up the i2c driver a second time.

Signed-off-by: Edward A. James <eajames@us.ibm.com>
---
 drivers/fsi/i2c/iic-fsi.c  | 125 +++------------------------------------------
 drivers/fsi/i2c/iic-mstr.c |  42 +++------------
 2 files changed, 14 insertions(+), 153 deletions(-)

diff --git a/drivers/fsi/i2c/iic-fsi.c b/drivers/fsi/i2c/iic-fsi.c
index 2c0aec9..6d5b045 100644
--- a/drivers/fsi/i2c/iic-fsi.c
+++ b/drivers/fsi/i2c/iic-fsi.c
@@ -36,60 +36,12 @@
 struct class* iic_fsi_class = 0;
 dev_t iic_devnum_start = 0;
 
-static const char iic_fsi_version[] = "3.0";
+static const char iic_fsi_version[] = "3.1";
 
 int iic_fsi_probe(struct device *dev);
 int iic_fsi_remove(struct device *dev);
-void iic_fsi_shutdown(struct device *dev);
 int iic_fsi_suspend(struct device *dev);
 int iic_fsi_resume(struct device *dev);
-static void iic_eng_release(struct kobject* kobj);
-
-/* callback function for when the reference count for an engine reaches 0 */
-static void iic_eng_release(struct kobject* kobj)
-{
-	iic_eng_t* eng = container_of(kobj, iic_eng_t, kobj);
-	struct device* dev = eng->dev;
-	unsigned long flags;
-
-	IENTER();
-
-	/*remove all busses associated with the engine */
-	spin_lock_irqsave(&eng->lock, flags);
-	while(eng->busses){
-		iic_bus_t* temp = eng->busses;
-		eng->busses = temp->next;
-		iic_delete_bus(iic_fsi_class, temp);
-	}
-
-	eng->enabled = 0x0ULL;
-	spin_unlock_irqrestore(&eng->lock, flags);
-
-
-	/* providing an arch specific cleanup routine is optional.
-	 * if not specified, use the default.
-	 */
-	if (iic_eng_ops_is_vaild(eng->ops)) {
-		if(eng->ops->cleanup_eng)
-		{
-			eng->ops->cleanup_eng(eng);
-		}
-		else
-		{
-			IDBGd(0, "free engine\n");
-			kfree(eng);
-		}
-	}
-
-	dev_set_drvdata(dev, 0);
-	kobject_put(&dev->kobj);
-
-	IEXIT(0);
-}
-
-static struct kobj_type iic_eng_ktype = {
-	.release = iic_eng_release,
-};
 
 int readb_wrap(iic_eng_t* eng, unsigned int addr, unsigned char *val, 
 	       iic_ffdc_t** ffdc)
@@ -223,7 +175,7 @@ int iic_add_ports(iic_eng_t* eng, uint64_t ports)
 
 	IENTER();
 
-	IFLDi(3, "Adding ports[0x%08x%08x] to eng[0x%08x]",
+	IFLDi(3, "Adding ports[0x%08x%08x] to eng[0x%08x]\n",
 	      (uint32_t)(ports >> 32),
 	      (uint32_t)ports,
 	      eng->id);
@@ -305,8 +257,6 @@ int iic_del_ports(iic_eng_t* eng, uint64_t ports)
 
 	/* walk unordered SLL and delete bus if it is in the ports bit mask */
 	spin_lock_irqsave(&eng->lock, flags);
-	if(test_bit(IIC_ENG_REMOVED, &eng->flags))
-		goto exit;
 	p_abusp = &eng->busses;
 	abusp = *p_abusp;
 	while(abusp)
@@ -316,7 +266,6 @@ int iic_del_ports(iic_eng_t* eng, uint64_t ports)
 			/* found a match, remove it */
 			*p_abusp = abusp->next;
 			eng->enabled &= ~(0x1ULL << abusp->port);
-			device_destroy(iic_fsi_class, abusp->devnum);
 			iic_delete_bus(iic_fsi_class, abusp);
 		}
 		else
@@ -327,12 +276,12 @@ int iic_del_ports(iic_eng_t* eng, uint64_t ports)
 		abusp = *p_abusp;
 	}
 
-exit:
 	spin_unlock_irqrestore(&eng->lock, flags);
 	IEXIT(0);
 	return 0;
 }
 
+#define IIC_FSI_PORTS	0xFFFULL
 /*
  * Called when an FSI IIC engine is plugged in.  
  * Causes creation of the /dev entry.
@@ -361,12 +310,11 @@ int iic_fsi_probe(struct device *dev)
 	iic_init_eng(eng);
 	set_bit(IIC_ENG_BLOCK, &eng->flags); //block until resumed
 	eng->id = 0x00F5112C;
-	IFLDi(1, "PROBE    eng[%08x]", eng->id);
+	IFLDi(1, "PROBE    eng[%08x]\n", eng->id);
 	eng->ra = &fsi_reg_access;
 	IFLDd(1, "vaddr=%#08lx\n", eng->base);
 	eng->dev = dev;
 	// The new kernel now requires 2 arguments
-	kobject_init(&eng->kobj, &iic_eng_ktype); //ref count = 1
 	eng->ops = iic_get_eng_ops(FSI_ENGID_I2C);
 	if(!eng->ops)
 	{
@@ -382,7 +330,7 @@ int iic_fsi_probe(struct device *dev)
 
 	IFLDd(1, "irq  = %d\n", eng->irq);
 
-	new_ports = 0xFFFULL;
+	new_ports = IIC_FSI_PORTS;
 	set_bit(IIC_ENG_P8_Z8_CENTAUR, &eng->flags);
 
 
@@ -394,21 +342,13 @@ int iic_fsi_probe(struct device *dev)
 	dev_set_drvdata(dev, eng);
 	eng->private_data = 0; //unused
 
-
-	/* set the callback function for when the eng ref count reaches 0 */
-	kobject_get(&eng->dev->kobj);
-
 	iic_fsi_resume(dev);
 
 error:
 	if(rc)
 	{
 		IFLDi(1, "IIC: iic_fsi_probe failed: %d\n", rc);
-		while(eng && eng->busses){
-			iic_bus_t* temp = eng->busses;
-			eng->busses = temp->next;
-			iic_delete_bus(iic_fsi_class, temp);
-		}
+		iic_del_ports(eng, new_ports);
 		if(eng)
 		{
 			kfree(eng);
@@ -430,9 +370,7 @@ error:
 int iic_fsi_remove(struct device* dev)
 {
 	int rc = 0;
-	iic_bus_t* bus;
 	iic_eng_t* eng = (iic_eng_t*)dev_get_drvdata(dev);
-	unsigned long flags;
 
 	IENTER();
        
@@ -453,62 +391,15 @@ int iic_fsi_remove(struct device* dev)
 	IFLDi(1, "REMOVE   eng[%08x]\n", eng->id);
 
 	/* Clean up device files immediately, don't wait for ref count */
-	spin_lock_irqsave(&eng->lock, flags);
-	bus = eng->busses;
-	while(bus)
-	{
-		/* causes hot unplug event */
-		device_destroy(iic_fsi_class, bus->devnum);
-		bus = bus->next;
-	}
-	spin_unlock_irqrestore(&eng->lock, flags);
-
+	iic_del_ports(eng, IIC_FSI_PORTS);
 	/* cleans up engine and bus structures if ref count is zero */
-	kobject_put(&eng->kobj);
+	kfree(eng);
 	
 error:
 	IEXIT(0);
 	return 0;
 }
 
-/* This function is called when a link is removed or the driver is unloaded.
- * It's job is to quiesce and disable the hardware if possible and unregister 
- * interrupts. It always precedes the remove function.
- *
- * The device may be in the resumed or suspended state when this function is
- * called.
- *
- * This function is no longer called for mcp5
- */
-void iic_fsi_shutdown(struct device *dev)
-{
-	int rc = 0;
-	iic_eng_t* eng = (iic_eng_t*)dev_get_drvdata(dev);
-
-	IENTER();
-	if(!eng || !eng->ops)
-	{
-		rc = -1;
-		goto error;
-	}
-	IFLDi(1, "SHUTDOWN eng[%08x]\n", eng->id);
-
-	/* set ENG_REMOVED flag so that aborted operations have status
-	 * set to ENOLINK (lost fsi link) instead of ENODEV (no lbus).
-	 */
-	set_bit(IIC_ENG_REMOVED, &eng->flags);
-
-	iic_fsi_suspend(dev);
-	
-error:
-	if(rc)
-	{
-		IFLDe(1, "iic_fsi_shutdown failed: %d\n", rc);
-	}
-	IEXIT(0);
-	return;
-}
-
 /* This function is called when we loose ownership or are preparing to give
  * up ownership of the local bus.  If we still own lbus, then we try to
  * gracefully halt any pending transfer.  No hot unplug events are caused by
diff --git a/drivers/fsi/i2c/iic-mstr.c b/drivers/fsi/i2c/iic-mstr.c
index 0d97671..5501b22 100644
--- a/drivers/fsi/i2c/iic-mstr.c
+++ b/drivers/fsi/i2c/iic-mstr.c
@@ -83,27 +83,7 @@ iic_opts_t iic_dflt_opts =
 	}
 };
 
-static const char iic_mstr_version[] = "3.0";
-
-/* save off the default cdev type pointer so we can call the default cdev
- * release function in our own bus release function
- */
-static struct kobj_type* cdev_dflt_type = 0;
-struct kobj_type iic_bus_type;
-
-/* funtion called when cdev object (embedded in bus object) ref count
- * reaches zero.  (prevents cdev memory from being freed to early)
- */
-void iic_bus_release(struct kobject* kobj)
-{
-	struct cdev *p = container_of(kobj, struct cdev, kobj);
-	iic_bus_t* bus = container_of(p, iic_bus_t, cdev);
-
-	IFLDi(1, "deleting bus[%08lx]\n", bus->bus_id);
-	if(cdev_dflt_type && cdev_dflt_type->release)
-		cdev_dflt_type->release(kobj);
-	kfree(bus);
-}
+static const char iic_mstr_version[] = "3.1";
 
 int iic_open(struct inode* inode, struct file* filp);
 int iic_release(struct inode* inode, struct file* filp);
@@ -167,7 +147,6 @@ int iic_common_open(iic_client_t ** o_client, iic_bus_t * bus, int engine_num)
 	client->tgid = current->tgid;
 	sema_init(&client->sem, 1);
 	init_waitqueue_head(&client->wait);
-	kobject_get(&bus->eng->kobj);
 	*o_client = client;
 
 exit:
@@ -262,7 +241,6 @@ int iic_common_release(iic_client_t * client)
 
         client->bus = 0;
         kfree(client);
-        kobject_put(&bus->eng->kobj);
 
         IEXIT(rc);
         return rc;
@@ -1170,6 +1148,7 @@ EXPORT_SYMBOL(iic_sideways_read);
 ssize_t iic_read(struct file *filp, char __user *buf, size_t count,
 		 loff_t *offset)
 {
+	int rc_copy;
 	ssize_t rc = count;
 	char *kbuf;
 	iic_client_t *client = (iic_client_t*)filp->private_data;
@@ -1203,7 +1182,7 @@ ssize_t iic_read(struct file *filp, char __user *buf, size_t count,
 	if (rc < 0)
 		goto free;
 
-	rc = copy_to_user(buf, kbuf, count);
+	rc_copy = copy_to_user(buf, kbuf, count);
 
 free:
 	kfree(kbuf);
@@ -2148,23 +2127,11 @@ iic_bus_t*  iic_create_bus(struct class* classp, iic_eng_t* eng,
 	bus->devnum = devnum;
 	bus->i2c_hz = 400000;
 	cdev_init(&bus->cdev, &iic_fops); // ref count = 1
-	/* since cdev is embedded in our bus structure, override the cdev
-	 * cleanup function with our own so that the bus object doesn't get
-	 * freed until the cdev ref count goes to zero.
-	 */
-	if(!cdev_dflt_type)
-	{
-		cdev_dflt_type = bus->cdev.kobj.ktype;
-		memcpy(&iic_bus_type, cdev_dflt_type, sizeof(iic_bus_type));
-		iic_bus_type.release = iic_bus_release;
-	}
-	bus->cdev.kobj.ktype = &iic_bus_type;
 	kobject_set_name(&bus->cdev.kobj, name);
 	rc = cdev_add(&bus->cdev, devnum, 1);
 	if(rc)
 	{
 		IFLDe(1, "cdev_add failed for bus %08lx\n", bus->bus_id);
-		kobject_put(&bus->cdev.kobj);
 		goto exit_cdev_add;
 	}
 
@@ -2186,6 +2153,7 @@ iic_bus_t*  iic_create_bus(struct class* classp, iic_eng_t* eng,
 exit_class_add:
 	cdev_del(&bus->cdev);
 exit_cdev_add:
+	kfree(bus);
 	bus = 0;
 exit:
 	IEXIT((int)bus);
@@ -2202,7 +2170,9 @@ void iic_delete_bus(struct class* classp, iic_bus_t* bus)
 		goto exit;
 	}
 	IFLDi(1, "cleanup bus[%08lx]\n", bus->bus_id);
+	device_destroy(classp, bus->devnum);
 	cdev_del(&bus->cdev);
+	kfree(bus);
 exit:
 	IEXIT(0);
 	return;
-- 
1.8.3.1

  reply	other threads:[~2017-02-10 16:49 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-10 16:49 [PATCH linux dev-4.7 v2 0/2] drivers: fsi: i2c Fixes Eddie James
2017-02-10 16:49 ` Eddie James [this message]
2017-02-10 16:59   ` [PATCH linux dev-4.7 v2 1/2] drivers: fsi: i2c fix probing Christopher Bostic
2017-02-13  2:03     ` Joel Stanley
2017-02-10 16:49 ` [PATCH linux dev-4.7 v2 2/2] drivers: fsi: i2c fix ports Eddie James
2017-02-13  2:02   ` Joel Stanley

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1486745362-7790-2-git-send-email-eajames@linux.vnet.ibm.com \
    --to=eajames@linux.vnet.ibm.com \
    --cc=cbostic@linux.vnet.ibm.com \
    --cc=eajames@us.ibm.com \
    --cc=joel@jms.id.au \
    --cc=openbmc@lists.ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.