[PATCH V2] Gadget: race between ffs_epfile_io() and ffs_func_eps_disable()
ffs_epfile_io() is called from userspace, while ffs_func_esp_disable() might be called from USB disconnect interrupt, the two functions would run in parallel but they are not well protected, that epfile->ep would be removed by ffs_func_esp_disable() during ffs_epfile_io() is referring this pointer, then it leads to kernel PANIC. The scenario is as below: Thread 1 Thread 2 || SyS_read dwc3_gadget_disconnect_interrupt || ffs_epfile_read reset_config || ffs_epfile_io ffs_func_eps_disable || - usb_ep_disable(): epfile->ep->ep->desc = NULL || usb_ep_align_maybe(): - it refers ep->desc->wMaxPacketSize- Signed-off-by: Chao Bi --- drivers/usb/gadget/f_fs.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 2e164dc..1e12b3e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) */ struct usb_gadget *gadget = epfile->ffs->gadget; + spin_lock_irq(>ffs->eps_lock); + /* In the meantime, endpoint got disabled or changed. */ + if (epfile->ep != ep) { + spin_unlock_irq(>ffs->eps_lock); + return -ESHUTDOWN; + } /* * Controller may require buffer size to be aligned to * maxpacketsize of an out endpoint. @@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) data_len = io_data->read ? usb_ep_align_maybe(gadget, ep->ep, io_data->len) : io_data->len; + spin_unlock_irq(>ffs->eps_lock); data = kmalloc(data_len, GFP_KERNEL); if (unlikely(!data)) -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V2] Gadget: race between ffs_epfile_io() and ffs_func_eps_disable()
ffs_epfile_io() is called from userspace, while ffs_func_esp_disable() might be called from USB disconnect interrupt, the two functions would run in parallel but they are not well protected, that epfile-ep would be removed by ffs_func_esp_disable() during ffs_epfile_io() is referring this pointer, then it leads to kernel PANIC. The scenario is as below: Thread 1 Thread 2 || SyS_read dwc3_gadget_disconnect_interrupt || ffs_epfile_read reset_config || ffs_epfile_io ffs_func_eps_disable || - usb_ep_disable(): epfile-ep-ep-desc = NULL || usb_ep_align_maybe(): - it refers ep-desc-wMaxPacketSize- Signed-off-by: Chao Bi chao...@intel.com --- drivers/usb/gadget/f_fs.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 2e164dc..1e12b3e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) */ struct usb_gadget *gadget = epfile-ffs-gadget; + spin_lock_irq(epfile-ffs-eps_lock); + /* In the meantime, endpoint got disabled or changed. */ + if (epfile-ep != ep) { + spin_unlock_irq(epfile-ffs-eps_lock); + return -ESHUTDOWN; + } /* * Controller may require buffer size to be aligned to * maxpacketsize of an out endpoint. @@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) data_len = io_data-read ? usb_ep_align_maybe(gadget, ep-ep, io_data-len) : io_data-len; + spin_unlock_irq(epfile-ffs-eps_lock); data = kmalloc(data_len, GFP_KERNEL); if (unlikely(!data)) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] Gadget: race between ffs_epfile_io() and ffs_func_eps_disable()
ffs_epfile_io() is called from userspace, while ffs_func_esp_disable() might be called from USB disconnect interrupt, the two functions would run in parallel but they are not well protected, that epfile->ep would be removed by ffs_func_esp_disable() during ffs_epfile_io() is referring this pointer, then it leads to kernel PANIC. The scenario is as below: Thread 1 Thread 2 || SyS_read dwc3_gadget_disconnect_interrupt || ffs_epfile_read reset_config || ffs_epfile_io ffs_func_eps_disable || - usb_ep_disable(): epfile->ep->ep->desc = NULL || usb_ep_align_maybe(): - it refers ep->desc->wMaxPacketSize- Signed-off-by: Chao Bi --- drivers/usb/gadget/f_fs.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 2e164dc..1e12b3e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) */ struct usb_gadget *gadget = epfile->ffs->gadget; + spin_lock_irq(>ffs->eps_lock); + /* In the meantime, endpoint got disabled or changed. */ + if (epfile->ep != ep) { + spin_unlock_irq(>ffs->eps_lock); + return -ESHUTDOWN; + } /* * Controller may require buffer size to be aligned to * maxpacketsize of an out endpoint. @@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) data_len = io_data->read ? usb_ep_align_maybe(gadget, ep->ep, io_data->len) : io_data->len; + spin_unlock_irq(>ffs->eps_lock); data = kmalloc(data_len, GFP_KERNEL); if (unlikely(!data)) -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] Gadget: race between ffs_epfile_io() and ffs_func_eps_disable()
ffs_epfile_io() is called from userspace, while ffs_func_esp_disable() might be called from USB disconnect interrupt, the two functions would run in parallel but they are not well protected, that epfile->ep would be removed by ffs_func_esp_disable() during ffs_epfile_io() is referring this pointer, then it leads to kernel PANIC. The scenario is as below: Thread 1 Thread 2 || SyS_read dwc3_gadget_disconnect_interrupt ||From 772c1c9ef451a9a84e48acf14ba613328920a2f4 Mon Sep 17 00:00:00 2001 From: channing Date: Wed, 2 Apr 2014 16:37:57 +0800 Subject: [PATCH] Gadget: race between ffs_epfile_io() and ffs_func_eps_disable() ffs_epfile_io() is called from userspace, while ffs_func_esp_disable() might be called from USB disconnect interrupt, the two functions would run in parallel but they are not well protected, that epfile->ep would be removed by ffs_func_esp_disable() during ffs_epfile_io() is referring this pointer, then it leads to kernel PANIC. The scenario is as below: Thread 1 Thread 2 || SyS_read dwc3_gadget_disconnect_interrupt || ffs_epfile_read reset_config || ffs_epfile_io ffs_func_eps_disable || - usb_ep_disable(): epfile->ep->ep->desc = NULL || usb_ep_align_maybe(): - it refers ep->desc->wMaxPacketSize- Signed-off-by: Chao Bi --- drivers/usb/gadget/f_fs.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 2e164dc..1e12b3e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) */ struct usb_gadget *gadget = epfile->ffs->gadget; + spin_lock_irq(>ffs->eps_lock); + /* In the meantime, endpoint got disabled or changed. */ + if (epfile->ep != ep) { + spin_unlock_irq(>ffs->eps_lock); + return -ESHUTDOWN; + } /* * Controller may require buffer size to be aligned to * maxpacketsize of an out endpoint. @@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) data_len = io_data->read ? usb_ep_align_maybe(gadget, ep->ep, io_data->len) : io_data->len; + spin_unlock_irq(>ffs->eps_lock); data = kmalloc(data_len, GFP_KERNEL); if (unlikely(!data)) -- 1.7.9.5 ffs_epfile_read reset_config || ffs_epfile_io ffs_func_eps_disable || - usb_ep_disable(): epfile->ep->ep->desc = NULL || usb_ep_align_maybe(): - it refers ep->desc->wMaxPacketSize- Signed-off-by: Chao Bi --- drivers/usb/gadget/f_fs.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 2e164dc..1e12b3e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) */ struct usb_gadget *gadget = epfile->ffs->gadget; + spin_lock_irq(>ffs->eps_lock); + /* In the meantime, endpoint got disabled or changed. */ + if (epfile->ep != ep) { + spin_unlock_irq(>ffs->eps_lock); + return -ESHUTDOWN; + } /* * Controller may require buffer size to be aligned to * maxpacketsize of an out endpoint. @@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) data_len = io_data->read ? usb_ep_align_maybe(gadget, ep->ep, io_data->len) : io_data->len; + spin_unlock_irq(>ffs->eps_lock); data = kmalloc(data_len, GFP_KERNEL); if (unlikely(!data)) -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message
[PATCH] Gadget: race between ffs_epfile_io() and ffs_func_eps_disable()
ffs_epfile_io() is called from userspace, while ffs_func_esp_disable() might be called from USB disconnect interrupt, the two functions would run in parallel but they are not well protected, that epfile-ep would be removed by ffs_func_esp_disable() during ffs_epfile_io() is referring this pointer, then it leads to kernel PANIC. The scenario is as below: Thread 1 Thread 2 || SyS_read dwc3_gadget_disconnect_interrupt ||From 772c1c9ef451a9a84e48acf14ba613328920a2f4 Mon Sep 17 00:00:00 2001 From: channing chao...@intel.com Date: Wed, 2 Apr 2014 16:37:57 +0800 Subject: [PATCH] Gadget: race between ffs_epfile_io() and ffs_func_eps_disable() ffs_epfile_io() is called from userspace, while ffs_func_esp_disable() might be called from USB disconnect interrupt, the two functions would run in parallel but they are not well protected, that epfile-ep would be removed by ffs_func_esp_disable() during ffs_epfile_io() is referring this pointer, then it leads to kernel PANIC. The scenario is as below: Thread 1 Thread 2 || SyS_read dwc3_gadget_disconnect_interrupt || ffs_epfile_read reset_config || ffs_epfile_io ffs_func_eps_disable || - usb_ep_disable(): epfile-ep-ep-desc = NULL || usb_ep_align_maybe(): - it refers ep-desc-wMaxPacketSize- Signed-off-by: Chao Bi chao...@intel.com --- drivers/usb/gadget/f_fs.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 2e164dc..1e12b3e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) */ struct usb_gadget *gadget = epfile-ffs-gadget; + spin_lock_irq(epfile-ffs-eps_lock); + /* In the meantime, endpoint got disabled or changed. */ + if (epfile-ep != ep) { + spin_unlock_irq(epfile-ffs-eps_lock); + return -ESHUTDOWN; + } /* * Controller may require buffer size to be aligned to * maxpacketsize of an out endpoint. @@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) data_len = io_data-read ? usb_ep_align_maybe(gadget, ep-ep, io_data-len) : io_data-len; + spin_unlock_irq(epfile-ffs-eps_lock); data = kmalloc(data_len, GFP_KERNEL); if (unlikely(!data)) -- 1.7.9.5 ffs_epfile_read reset_config || ffs_epfile_io ffs_func_eps_disable || - usb_ep_disable(): epfile-ep-ep-desc = NULL || usb_ep_align_maybe(): - it refers ep-desc-wMaxPacketSize- Signed-off-by: Chao Bi chao...@intel.com --- drivers/usb/gadget/f_fs.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 2e164dc..1e12b3e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) */ struct usb_gadget *gadget = epfile-ffs-gadget; + spin_lock_irq(epfile-ffs-eps_lock); + /* In the meantime, endpoint got disabled or changed. */ + if (epfile-ep != ep) { + spin_unlock_irq(epfile-ffs-eps_lock); + return -ESHUTDOWN; + } /* * Controller may require buffer size to be aligned to * maxpacketsize of an out endpoint. @@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) data_len = io_data-read ? usb_ep_align_maybe(gadget, ep-ep, io_data-len) : io_data-len; + spin_unlock_irq(epfile-ffs-eps_lock); data = kmalloc(data_len, GFP_KERNEL); if (unlikely(!data)) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org
[PATCH] Gadget: race between ffs_epfile_io() and ffs_func_eps_disable()
ffs_epfile_io() is called from userspace, while ffs_func_esp_disable() might be called from USB disconnect interrupt, the two functions would run in parallel but they are not well protected, that epfile-ep would be removed by ffs_func_esp_disable() during ffs_epfile_io() is referring this pointer, then it leads to kernel PANIC. The scenario is as below: Thread 1 Thread 2 || SyS_read dwc3_gadget_disconnect_interrupt || ffs_epfile_read reset_config || ffs_epfile_io ffs_func_eps_disable || - usb_ep_disable(): epfile-ep-ep-desc = NULL || usb_ep_align_maybe(): - it refers ep-desc-wMaxPacketSize- Signed-off-by: Chao Bi chao...@intel.com --- drivers/usb/gadget/f_fs.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 2e164dc..1e12b3e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) */ struct usb_gadget *gadget = epfile-ffs-gadget; + spin_lock_irq(epfile-ffs-eps_lock); + /* In the meantime, endpoint got disabled or changed. */ + if (epfile-ep != ep) { + spin_unlock_irq(epfile-ffs-eps_lock); + return -ESHUTDOWN; + } /* * Controller may require buffer size to be aligned to * maxpacketsize of an out endpoint. @@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) data_len = io_data-read ? usb_ep_align_maybe(gadget, ep-ep, io_data-len) : io_data-len; + spin_unlock_irq(epfile-ffs-eps_lock); data = kmalloc(data_len, GFP_KERNEL); if (unlikely(!data)) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] WIFI: handle a neglected case in nl80211_new_interface()
On Thu, 2013-11-28 at 11:53 +0800, Chao Bi wrote: > On Wed, 2013-11-27 at 20:43 +0530, Ujjal Roy wrote: > > Hi, > > > > > > We can use IS_ERR_OR_NULL(wdev) to check NULL as well as error value. > > > > Thanks, > > UjjaL > > > > On Wed, Nov 27, 2013 at 8:30 AM, Chao Bi wrote: > > In nl80211_new_interface(), it calls rdev_add_virtual_intf() to > > create > > a new interface, however, it only checks whether returned value is > > err > > code, but doesn't check if returned value is NULL. The returned > > Thanks Ujjal. I'll update it. > Hi all, This patch is not valid, I further check the nl80211 API introduce, don't need to handle this NULL return value because it bans NULL feedback of add_virtual_intf() API in cfg80211.h. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] WIFI: handle a neglected case in nl80211_new_interface()
On Wed, 2013-11-27 at 20:43 +0530, Ujjal Roy wrote: > Hi, > > > We can use IS_ERR_OR_NULL(wdev) to check NULL as well as error value. > > Thanks, > UjjaL > > On Wed, Nov 27, 2013 at 8:30 AM, Chao Bi wrote: > In nl80211_new_interface(), it calls rdev_add_virtual_intf() to create > a new interface, however, it only checks whether returned value is err > code, but doesn't check if returned value is NULL. The returned Thanks Ujjal. I'll update it. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] WIFI: handle a neglected case in nl80211_new_interface()
On Wed, 2013-11-27 at 20:43 +0530, Ujjal Roy wrote: Hi, We can use IS_ERR_OR_NULL(wdev) to check NULL as well as error value. Thanks, UjjaL On Wed, Nov 27, 2013 at 8:30 AM, Chao Bi chao...@intel.com wrote: In nl80211_new_interface(), it calls rdev_add_virtual_intf() to create a new interface, however, it only checks whether returned value is err code, but doesn't check if returned value is NULL. The returned Thanks Ujjal. I'll update it. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] WIFI: handle a neglected case in nl80211_new_interface()
On Thu, 2013-11-28 at 11:53 +0800, Chao Bi wrote: On Wed, 2013-11-27 at 20:43 +0530, Ujjal Roy wrote: Hi, We can use IS_ERR_OR_NULL(wdev) to check NULL as well as error value. Thanks, UjjaL On Wed, Nov 27, 2013 at 8:30 AM, Chao Bi chao...@intel.com wrote: In nl80211_new_interface(), it calls rdev_add_virtual_intf() to create a new interface, however, it only checks whether returned value is err code, but doesn't check if returned value is NULL. The returned Thanks Ujjal. I'll update it. Hi all, This patch is not valid, I further check the nl80211 API introduce, don't need to handle this NULL return value because it bans NULL feedback of add_virtual_intf() API in cfg80211.h. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] WIFI: handle a neglected case in nl80211_new_interface()
In nl80211_new_interface(), it calls rdev_add_virtual_intf() to create a new interface, however, it only checks whether returned value is err code, but doesn't check if returned value is NULL. The returned value could be NULL, for example, memory allocation failed when creating a new interface. when get a NULL returned value, nl80211_new_interface() is expected to return but it actually runs down to access the NULL pointer, this could lead to a panic. Signed-off-by: Chao Bi --- net/wireless/nl80211.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a1eb210..27feeaf 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2512,7 +2512,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) wdev = rdev_add_virtual_intf(rdev, nla_data(info->attrs[NL80211_ATTR_IFNAME]), type, err ? NULL : , ); - if (IS_ERR(wdev)) { + if (!wdev || IS_ERR(wdev)) { nlmsg_free(msg); return PTR_ERR(wdev); } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] WIFI: handle a neglected case in nl80211_new_interface()
In nl80211_new_interface(), it calls rdev_add_virtual_intf() to create a new interface, however, it only checks whether returned value is err code, but doesn't check if returned value is NULL. The returned value could be NULL, for example, memory allocation failed when creating a new interface. when get a NULL returned value, nl80211_new_interface() is expected to return but it actually runs down to access the NULL pointer, this could lead to a panic. Signed-off-by: Chao Bi chao...@intel.com --- net/wireless/nl80211.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a1eb210..27feeaf 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2512,7 +2512,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) wdev = rdev_add_virtual_intf(rdev, nla_data(info-attrs[NL80211_ATTR_IFNAME]), type, err ? NULL : flags, params); - if (IS_ERR(wdev)) { + if (!wdev || IS_ERR(wdev)) { nlmsg_free(msg); return PTR_ERR(wdev); } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V3] n_gsm: race between ld close and gsmtty open
ttyA has ld associated to n_gsm, when ttyA is closing, it triggers to release gsmttyB's ld data dlci[B], then race would happen if gsmttyB is opening in parallel. (Note: This patch set differs from previous set in that it uses mutex instead of spin lock to avoid race, so that it avoids sleeping in automic context) Here are race cases we found recently in test: CASE #1 releasing dlci[B] race with gsmtty_install(gsmttyB), then panic in gsmtty_open(gsmttyB), as below: tty_release(ttyA) tty_open(gsmttyB) | | - gsmtty_install(gsmttyB) | | -gsm_dlci_alloc(gsmttyB) => alloc dlci[B] tty_ldisc_release(ttyA) - | | gsm_dlci_release(dlci[B]) - | | gsm_dlci_free(dlci[B])- | | - gsmtty_open(gsmttyB) gsmtty_open() { struct gsm_dlci *dlci = tty->driver_data; => here it uses dlci[B] ... } In gsmtty_open(gsmttyA), it uses dlci[B] which was release, so hit a panic. = CASE #2 = releasing dlci[0] race with gsmtty_install(gsmttyB), then panic in gsmtty_open(), as below: tty_release(ttyA) tty_open(gsmttyB) | | - gsmtty_install(gsmttyB) | | -gsm_dlci_alloc(gsmttyB) => alloc dlci[B] | | - gsmtty_open(gsmttyB) fail | | - tty_release(gsmttyB) | | - gsmtty_close(gsmttyB) | | -gsmtty_detach_dlci(dlci[B]) | | - dlci_put(dlci[B]) | | tty_ldisc_release(ttyA) - | | gsm_dlci_release(dlci[0]) - | | gsm_dlci_free(dlci[0])- | | - dlci_put(dlci[0]) In gsmtty_detach_dlci(dlci[B]), it tries to use dlci[0] which was released, then hit panic. = IMHO, n_gsm tty operations would refer released ldisc, as long as gsm_dlci_release() has chance to release ldisc data when some gsmtty operations are ongoing.. This patch is try to avoid it by: 1) in n_gsm driver, use a global gsm mutex lock to avoid gsm_dlci_release() run in parallel with gsmtty_install(); 2) Increase dlci's ref count in gsmtty_install() instead of in gsmtty_open(), the purpose is to prevent gsm_dlci_release() releasing dlci after gsmtty_install() allocats dlci but before gsmtty_open increases dlci's ref count; 3) Decrease dlci's ref count in gsmtty_remove(), a tty framework API, this is the opposite process of step 2). Signed-off-by: Chao Bi --- drivers/tty/n_gsm.c | 39 +-- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c0f76da..d514396 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -194,6 +194,7 @@ struct gsm_control { struct gsm_mux { struct tty_struct *tty; /* The tty our ldisc is bound to */ spinlock_t lock; + struct mutex mutex; unsigned int num; struct kref ref; @@ -2054,9 +2055,11 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) dlci->state == DLCI_CLOSED); } /* Free up any link layer users */ + mutex_lock(>mutex); for (i = 0; i < NUM_DLCI; i++) if (gsm->dlci[i]) gsm_dlci_release(gsm->dlci[i]); + mutex_unlock(>mutex); /* Now wipe the queues */ list_for_each_entry_safe(txq, ntxq, >tx_list, list) kfree(txq); @@ -2170,6 +2173,7 @@ struct gsm_mux *gsm_alloc_mux(void) return NULL; } spin_lock_init(>lock); + mutex_init(>mutex); kref_init(>ref); INIT_LIST_HEAD(>tx_list); @@ -2909,23 +2913,33 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) This is ok from a locking perspective as we don't have to worry about this if DLC
[PATCH V3] n_gsm: race between ld close and gsmtty open
ttyA has ld associated to n_gsm, when ttyA is closing, it triggers to release gsmttyB's ld data dlci[B], then race would happen if gsmttyB is opening in parallel. (Note: This patch set differs from previous set in that it uses mutex instead of spin lock to avoid race, so that it avoids sleeping in automic context) Here are race cases we found recently in test: CASE #1 releasing dlci[B] race with gsmtty_install(gsmttyB), then panic in gsmtty_open(gsmttyB), as below: tty_release(ttyA) tty_open(gsmttyB) | | - gsmtty_install(gsmttyB) | | -gsm_dlci_alloc(gsmttyB) = alloc dlci[B] tty_ldisc_release(ttyA) - | | gsm_dlci_release(dlci[B]) - | | gsm_dlci_free(dlci[B])- | | - gsmtty_open(gsmttyB) gsmtty_open() { struct gsm_dlci *dlci = tty-driver_data; = here it uses dlci[B] ... } In gsmtty_open(gsmttyA), it uses dlci[B] which was release, so hit a panic. = CASE #2 = releasing dlci[0] race with gsmtty_install(gsmttyB), then panic in gsmtty_open(), as below: tty_release(ttyA) tty_open(gsmttyB) | | - gsmtty_install(gsmttyB) | | -gsm_dlci_alloc(gsmttyB) = alloc dlci[B] | | - gsmtty_open(gsmttyB) fail | | - tty_release(gsmttyB) | | - gsmtty_close(gsmttyB) | | -gsmtty_detach_dlci(dlci[B]) | | - dlci_put(dlci[B]) | | tty_ldisc_release(ttyA) - | | gsm_dlci_release(dlci[0]) - | | gsm_dlci_free(dlci[0])- | | - dlci_put(dlci[0]) In gsmtty_detach_dlci(dlci[B]), it tries to use dlci[0] which was released, then hit panic. = IMHO, n_gsm tty operations would refer released ldisc, as long as gsm_dlci_release() has chance to release ldisc data when some gsmtty operations are ongoing.. This patch is try to avoid it by: 1) in n_gsm driver, use a global gsm mutex lock to avoid gsm_dlci_release() run in parallel with gsmtty_install(); 2) Increase dlci's ref count in gsmtty_install() instead of in gsmtty_open(), the purpose is to prevent gsm_dlci_release() releasing dlci after gsmtty_install() allocats dlci but before gsmtty_open increases dlci's ref count; 3) Decrease dlci's ref count in gsmtty_remove(), a tty framework API, this is the opposite process of step 2). Signed-off-by: Chao Bi chao...@intel.com --- drivers/tty/n_gsm.c | 39 +-- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c0f76da..d514396 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -194,6 +194,7 @@ struct gsm_control { struct gsm_mux { struct tty_struct *tty; /* The tty our ldisc is bound to */ spinlock_t lock; + struct mutex mutex; unsigned int num; struct kref ref; @@ -2054,9 +2055,11 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) dlci-state == DLCI_CLOSED); } /* Free up any link layer users */ + mutex_lock(gsm-mutex); for (i = 0; i NUM_DLCI; i++) if (gsm-dlci[i]) gsm_dlci_release(gsm-dlci[i]); + mutex_unlock(gsm-mutex); /* Now wipe the queues */ list_for_each_entry_safe(txq, ntxq, gsm-tx_list, list) kfree(txq); @@ -2170,6 +2173,7 @@ struct gsm_mux *gsm_alloc_mux(void) return NULL; } spin_lock_init(gsm-lock); + mutex_init(gsm-mutex); kref_init(gsm-ref); INIT_LIST_HEAD(gsm-tx_list); @@ -2909,23 +2913,33 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) This is ok from a locking perspective as we don't have to worry about this if DLCI0 is lost
[PATCH] SPI: SSP SPI Controller driver v3
This patch is to implement SSP SPI controller driver, which has been applied and validated on intel Moorestown & Medfield platform. The patch are originated by Ken Mills and Sylvain Centelles , migrating to lateset Linux mainline SPI framework by Channing and Chen Jun according to their integration & validation on Medfield platform. Signed-off-by: Ken Mills Signed-off-by: Sylvain Centelles Signed-off-by: channing Signed-off-by: Chen Jun --- drivers/spi/Kconfig |9 + drivers/spi/Makefile |1 + drivers/spi/spi-intel-mid-ssp.c | 1614 + include/linux/spi/spi-intel-mid-ssp.h | 103 +++ 4 files changed, 1727 insertions(+), 0 deletions(-) create mode 100644 drivers/spi/spi-intel-mid-ssp.c create mode 100644 include/linux/spi/spi-intel-mid-ssp.h diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 2e188e1..6285f17 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -186,6 +186,15 @@ config SPI_IMX This enables using the Freescale i.MX SPI controllers in master mode. +config SPI_INTEL_MID_SSP + tristate "SSP SPI controller driver for Intel MID platforms" + depends on SPI_MASTER && INTEL_MID_DMAC + help + This is the unified SSP SPI master controller driver for + the Intel MID platforms, handling Moorestown & Medfield, + master clock mode. + It supports Bulverde SSP core. + config SPI_LM70_LLP tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)" depends on PARPORT && EXPERIMENTAL diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 64e970b..1738966 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_SPI_FSL_ESPI)+= spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o obj-$(CONFIG_SPI_IMX) += spi-imx.o +obj-$(CONFIG_SPI_INTEL_MID_SSP)+= spi-intel-mid-ssp.o obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o diff --git a/drivers/spi/spi-intel-mid-ssp.c b/drivers/spi/spi-intel-mid-ssp.c new file mode 100644 index 000..440c4a2 --- /dev/null +++ b/drivers/spi/spi-intel-mid-ssp.c @@ -0,0 +1,1614 @@ +/* + * spi-intel-mid-ssp.c + * This driver supports Bulverde SSP core used on Intel MID platforms + * It supports SSP of Moorestown & Medfield platforms and handles clock + * slave & master modes. + * + * Copyright (c) 2010, Intel Corporation. + * Ken Mills + * Sylvain Centelles + * Jun Chen + * Chao Bi + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* + * Note: + * + * Supports DMA and non-interrupt polled transfers. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCI_MRST_DMAC1_ID 0x0814 +#define PCI_MDFL_DMAC1_ID 0x0827 + +#define SSP_NOT_SYNC BIT(22) +#define MAX_SPI_TRANSFER_SIZE 8192 +#define MAX_BITBANGING_LOOP 1 +#define SPI_FIFO_SIZE 16 + +/* PM QoS define(usec) */ +#define MIN_EXIT_LATENCY 20 + +/* SPI DMA max transfer time */ +#define SSP_SPI_DMA_TIMEOUT 100 + +/* SSP assignement configuration from PCI config */ +#define SSP_CFG_GET_MODE(ssp_cfg) ((ssp_cfg) & 0x07) +#define SSP_CFG_GET_SPI_BUS_NB(ssp_cfg)(((ssp_cfg) >> 3) & 0x07) +#define SSP_CFG_IS_SPI_SLAVE(ssp_cfg) ((ssp_cfg) & BIT(6)) +#define SSP_CFG_SPI_MODE_ID1 +/* adid field offset is 6 inside the vendor specific capability */ +#define VNDR_CAPABILITY_ADID_OFFSET6 + +/* Driver's quirk flags + * This workarround bufferizes data in the audio fabric SDRAM from + * where the DMA transfers will operate. Should be enabled only for + * SPI slave mode. */ +#define QUIRKS_SRAM_ADDITIONAL_CPY 1 +/* If set the trailing bytes won't be handled by the DMA. + * Trailing byte feature not fully available. */ +#define QUIRKS_DMA_USE_NO_TRAIL2 +/* If set, the driver will use PM_QOS to reduce the latency + * introduced by the deeper C-states which may produce over/under + * run issues. Must be used i
[PATCH] SPI: SSP SPI Controller driver
This patch is to implement SSP SPI controller driver, which has been applied and validated on intel Moorestown & Medfield platform. The patch are originated by Ken Mills and Sylvain Centelles , migrating to lateset Linux mainline SPI framework by Channing and Chen Jun according to their integration & validation on Medfield platform. Signed-off-by: Ken Mills Signed-off-by: Sylvain Centelles Signed-off-by: channing Signed-off-by: Chen Jun --- drivers/spi/Kconfig |9 + drivers/spi/Makefile |1 + drivers/spi/spi-intel-mid-ssp.c | 1633 + include/linux/spi/spi-intel-mid-ssp.h | 103 +++ 4 files changed, 1746 insertions(+), 0 deletions(-) create mode 100644 drivers/spi/spi-intel-mid-ssp.c create mode 100644 include/linux/spi/spi-intel-mid-ssp.h diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 2e188e1..6285f17 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -186,6 +186,15 @@ config SPI_IMX This enables using the Freescale i.MX SPI controllers in master mode. +config SPI_INTEL_MID_SSP + tristate "SSP SPI controller driver for Intel MID platforms" + depends on SPI_MASTER && INTEL_MID_DMAC + help + This is the unified SSP SPI master controller driver for + the Intel MID platforms, handling Moorestown & Medfield, + master clock mode. + It supports Bulverde SSP core. + config SPI_LM70_LLP tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)" depends on PARPORT && EXPERIMENTAL diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 64e970b..1738966 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_SPI_FSL_ESPI)+= spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o obj-$(CONFIG_SPI_IMX) += spi-imx.o +obj-$(CONFIG_SPI_INTEL_MID_SSP)+= spi-intel-mid-ssp.o obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o diff --git a/drivers/spi/spi-intel-mid-ssp.c b/drivers/spi/spi-intel-mid-ssp.c new file mode 100644 index 000..760156e --- /dev/null +++ b/drivers/spi/spi-intel-mid-ssp.c @@ -0,0 +1,1633 @@ +/* + * spi-intel-mid-ssp.c + * This driver supports Bulverde SSP core used on Intel MID platforms + * It supports SSP of Moorestown & Medfield platforms and handles clock + * slave & master modes. + * + * Copyright (c) 2010, Intel Corporation. + * Ken Mills + * Sylvain Centelles + * Jun Chen + * Chao Bi + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* + * Note: + * + * Supports DMA and non-interrupt polled transfers. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCI_MRST_DMAC1_ID 0x0814 +#define PCI_MDFL_DMAC1_ID 0x0827 + +#define SSP_NOT_SYNC 0x40 +#define MAX_SPI_TRANSFER_SIZE 8192 +#define MAX_BITBANGING_LOOP 1 +#define SPI_FIFO_SIZE 16 + +/* PM QoS define */ +#define MIN_EXIT_LATENCY 20 + +/* SPI DMA max transfer time */ +#define SSP_SPI_DMA_TIMEOUT 100 + +/* SSP assignement configuration from PCI config */ +#define SSP_CFG_GET_MODE(ssp_cfg) ((ssp_cfg) & 0x07) +#define SSP_CFG_GET_SPI_BUS_NB(ssp_cfg)(((ssp_cfg) >> 3) & 0x07) +#define SSP_CFG_IS_SPI_SLAVE(ssp_cfg) ((ssp_cfg) & 0x40) +#define SSP_CFG_SPI_MODE_ID1 +/* adid field offset is 6 inside the vendor specific capability */ +#define VNDR_CAPABILITY_ADID_OFFSET6 + +/* Driver's quirk flags */ +/* This workarround bufferizes data in the audio fabric SDRAM from */ +/* where the DMA transfers will operate. Should be enabled only for */ +/* SPI slave mode. */ +#define QUIRKS_SRAM_ADDITIONAL_CPY 1 +/* If set the trailing bytes won't be handled by the DMA. */ +/* Trailing byte feature not fully available. */ +#define QUIRKS_DMA_USE_NO_TRAIL2 +/* If set, the driver will use PM_QOS to reduce the latency */ +/* i
[PATCH] SPI: SSP SPI Controller driver v3
This patch is to implement SSP SPI controller driver, which has been applied and validated on intel Moorestown Medfield platform. The patch are originated by Ken Mills ken.k.mi...@intel.com and Sylvain Centelles sylvain.centel...@intel.com, migrating to lateset Linux mainline SPI framework by Channing chao...@intel.com and Chen Jun jun.d.c...@intel.com according to their integration validation on Medfield platform. Signed-off-by: Ken Mills ken.k.mi...@intel.com Signed-off-by: Sylvain Centelles sylvain.centel...@intel.com Signed-off-by: channing chao...@intel.com Signed-off-by: Chen Jun jun.d.c...@intel.com --- drivers/spi/Kconfig |9 + drivers/spi/Makefile |1 + drivers/spi/spi-intel-mid-ssp.c | 1614 + include/linux/spi/spi-intel-mid-ssp.h | 103 +++ 4 files changed, 1727 insertions(+), 0 deletions(-) create mode 100644 drivers/spi/spi-intel-mid-ssp.c create mode 100644 include/linux/spi/spi-intel-mid-ssp.h diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 2e188e1..6285f17 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -186,6 +186,15 @@ config SPI_IMX This enables using the Freescale i.MX SPI controllers in master mode. +config SPI_INTEL_MID_SSP + tristate SSP SPI controller driver for Intel MID platforms + depends on SPI_MASTER INTEL_MID_DMAC + help + This is the unified SSP SPI master controller driver for + the Intel MID platforms, handling Moorestown Medfield, + master clock mode. + It supports Bulverde SSP core. + config SPI_LM70_LLP tristate Parallel port adapter for LM70 eval board (DEVELOPMENT) depends on PARPORT EXPERIMENTAL diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 64e970b..1738966 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_SPI_FSL_ESPI)+= spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o obj-$(CONFIG_SPI_IMX) += spi-imx.o +obj-$(CONFIG_SPI_INTEL_MID_SSP)+= spi-intel-mid-ssp.o obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o diff --git a/drivers/spi/spi-intel-mid-ssp.c b/drivers/spi/spi-intel-mid-ssp.c new file mode 100644 index 000..440c4a2 --- /dev/null +++ b/drivers/spi/spi-intel-mid-ssp.c @@ -0,0 +1,1614 @@ +/* + * spi-intel-mid-ssp.c + * This driver supports Bulverde SSP core used on Intel MID platforms + * It supports SSP of Moorestown Medfield platforms and handles clock + * slave master modes. + * + * Copyright (c) 2010, Intel Corporation. + * Ken Mills ken.k.mi...@intel.com + * Sylvain Centelles sylvain.centel...@intel.com + * Jun Chen jun.d.c...@intel.com + * Chao Bi chao...@intel.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* + * Note: + * + * Supports DMA and non-interrupt polled transfers. + * + */ + +#include linux/delay.h +#include linux/interrupt.h +#include linux/highmem.h +#include linux/init.h +#include linux/interrupt.h +#include linux/dma-mapping.h +#include linux/intel_mid_dma.h +#include linux/pm_qos.h +#include linux/module.h +#include linux/spi/spi-intel-mid-ssp.h +#include linux/bitops.h + +#define PCI_MRST_DMAC1_ID 0x0814 +#define PCI_MDFL_DMAC1_ID 0x0827 + +#define SSP_NOT_SYNC BIT(22) +#define MAX_SPI_TRANSFER_SIZE 8192 +#define MAX_BITBANGING_LOOP 1 +#define SPI_FIFO_SIZE 16 + +/* PM QoS define(usec) */ +#define MIN_EXIT_LATENCY 20 + +/* SPI DMA max transfer time */ +#define SSP_SPI_DMA_TIMEOUT 100 + +/* SSP assignement configuration from PCI config */ +#define SSP_CFG_GET_MODE(ssp_cfg) ((ssp_cfg) 0x07) +#define SSP_CFG_GET_SPI_BUS_NB(ssp_cfg)(((ssp_cfg) 3) 0x07) +#define SSP_CFG_IS_SPI_SLAVE(ssp_cfg) ((ssp_cfg) BIT(6)) +#define SSP_CFG_SPI_MODE_ID1 +/* adid field offset is 6 inside the vendor specific capability */ +#define VNDR_CAPABILITY_ADID_OFFSET6 + +/* Driver's quirk flags + * This workarround bufferizes data in the audio fabric SDRAM from + * where the DMA transfers will operate. Should be enabled only for + * SPI slave mode. */ +#define
[PATCH] SPI: SSP SPI Controller driver
This patch is to implement SSP SPI controller driver, which has been applied and validated on intel Moorestown Medfield platform. The patch are originated by Ken Mills ken.k.mi...@intel.com and Sylvain Centelles sylvain.centel...@intel.com, migrating to lateset Linux mainline SPI framework by Channing chao...@intel.com and Chen Jun jun.d.c...@intel.com according to their integration validation on Medfield platform. Signed-off-by: Ken Mills ken.k.mi...@intel.com Signed-off-by: Sylvain Centelles sylvain.centel...@intel.com Signed-off-by: channing chao...@intel.com Signed-off-by: Chen Jun jun.d.c...@intel.com --- drivers/spi/Kconfig |9 + drivers/spi/Makefile |1 + drivers/spi/spi-intel-mid-ssp.c | 1633 + include/linux/spi/spi-intel-mid-ssp.h | 103 +++ 4 files changed, 1746 insertions(+), 0 deletions(-) create mode 100644 drivers/spi/spi-intel-mid-ssp.c create mode 100644 include/linux/spi/spi-intel-mid-ssp.h diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 2e188e1..6285f17 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -186,6 +186,15 @@ config SPI_IMX This enables using the Freescale i.MX SPI controllers in master mode. +config SPI_INTEL_MID_SSP + tristate SSP SPI controller driver for Intel MID platforms + depends on SPI_MASTER INTEL_MID_DMAC + help + This is the unified SSP SPI master controller driver for + the Intel MID platforms, handling Moorestown Medfield, + master clock mode. + It supports Bulverde SSP core. + config SPI_LM70_LLP tristate Parallel port adapter for LM70 eval board (DEVELOPMENT) depends on PARPORT EXPERIMENTAL diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 64e970b..1738966 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_SPI_FSL_ESPI)+= spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o obj-$(CONFIG_SPI_IMX) += spi-imx.o +obj-$(CONFIG_SPI_INTEL_MID_SSP)+= spi-intel-mid-ssp.o obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o diff --git a/drivers/spi/spi-intel-mid-ssp.c b/drivers/spi/spi-intel-mid-ssp.c new file mode 100644 index 000..760156e --- /dev/null +++ b/drivers/spi/spi-intel-mid-ssp.c @@ -0,0 +1,1633 @@ +/* + * spi-intel-mid-ssp.c + * This driver supports Bulverde SSP core used on Intel MID platforms + * It supports SSP of Moorestown Medfield platforms and handles clock + * slave master modes. + * + * Copyright (c) 2010, Intel Corporation. + * Ken Mills ken.k.mi...@intel.com + * Sylvain Centelles sylvain.centel...@intel.com + * Jun Chen jun.d.c...@intel.com + * Chao Bi chao...@intel.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* + * Note: + * + * Supports DMA and non-interrupt polled transfers. + * + */ + +#include linux/delay.h +#include linux/interrupt.h +#include linux/highmem.h +#include linux/init.h +#include linux/interrupt.h +#include linux/dma-mapping.h +#include linux/intel_mid_dma.h +#include linux/pm_qos.h +#include linux/module.h +#include linux/spi/spi-intel-mid-ssp.h + +#define PCI_MRST_DMAC1_ID 0x0814 +#define PCI_MDFL_DMAC1_ID 0x0827 + +#define SSP_NOT_SYNC 0x40 +#define MAX_SPI_TRANSFER_SIZE 8192 +#define MAX_BITBANGING_LOOP 1 +#define SPI_FIFO_SIZE 16 + +/* PM QoS define */ +#define MIN_EXIT_LATENCY 20 + +/* SPI DMA max transfer time */ +#define SSP_SPI_DMA_TIMEOUT 100 + +/* SSP assignement configuration from PCI config */ +#define SSP_CFG_GET_MODE(ssp_cfg) ((ssp_cfg) 0x07) +#define SSP_CFG_GET_SPI_BUS_NB(ssp_cfg)(((ssp_cfg) 3) 0x07) +#define SSP_CFG_IS_SPI_SLAVE(ssp_cfg) ((ssp_cfg) 0x40) +#define SSP_CFG_SPI_MODE_ID1 +/* adid field offset is 6 inside the vendor specific capability */ +#define VNDR_CAPABILITY_ADID_OFFSET6 + +/* Driver's quirk flags */ +/* This workarround bufferizes data in the audio fabric SDRAM from */ +/* where the DMA transfers will operate. Should be enabled only for */ +/* SPI slave mode
[PATCH] serial:ifx6x60:Keep word size accordance with SPI controller
As protocol driver, IFX SPI driver initiate to setup SPI master with default SPI word size as 16 bit/word, however, SPI master may not adopt this default value due to SPI controller's capability, it might choose an available value by itself and set it to spi_device.bits_per_word. In order to keep align with Controller, IFX driver should make use of this value during SPI transfer, but the default one. Signed-off-by: Chen Jun Signed-off-by: channing --- drivers/tty/serial/ifx6x60.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 675d94a..5919992 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -810,7 +810,8 @@ static void ifx_spi_io(unsigned long data) ifx_dev->spi_xfer.cs_change = 0; ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz; /* ifx_dev->spi_xfer.speed_hz = 390625; */ - ifx_dev->spi_xfer.bits_per_word = spi_bpw; + ifx_dev->spi_xfer.bits_per_word = + ifx_dev->spi_dev->bits_per_word; ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer; ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer; -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] serial:ifx6x60:Delete SPI timer when shut down port
When shut down SPI port, it's possible that MRDY has been asserted and a SPI timer was activated waiting for SRDY assert, in the case, it needs to delete this timer. Signed-off-by: Chen Jun Signed-off-by: channing --- drivers/tty/serial/ifx6x60.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 675d94a..7eed323 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -637,6 +637,7 @@ static void ifx_port_shutdown(struct tty_port *port) clear_bit(IFX_SPI_STATE_IO_AVAILABLE, _dev->flags); mrdy_set_low(ifx_dev); + del_timer(_dev->spi_timer); clear_bit(IFX_SPI_STATE_TIMER_PENDING, _dev->flags); tasklet_kill(_dev->io_work_tasklet); } -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] serial:ifx6x60:Delete SPI timer when shut down port
When shut down SPI port, it's possible that MRDY has been asserted and a SPI timer was activated waiting for SRDY assert, in the case, it needs to delete this timer. Signed-off-by: Chen Jun jun.d.c...@intel.com Signed-off-by: channing chao...@intel.com --- drivers/tty/serial/ifx6x60.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 675d94a..7eed323 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -637,6 +637,7 @@ static void ifx_port_shutdown(struct tty_port *port) clear_bit(IFX_SPI_STATE_IO_AVAILABLE, ifx_dev-flags); mrdy_set_low(ifx_dev); + del_timer(ifx_dev-spi_timer); clear_bit(IFX_SPI_STATE_TIMER_PENDING, ifx_dev-flags); tasklet_kill(ifx_dev-io_work_tasklet); } -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] serial:ifx6x60:Keep word size accordance with SPI controller
As protocol driver, IFX SPI driver initiate to setup SPI master with default SPI word size as 16 bit/word, however, SPI master may not adopt this default value due to SPI controller's capability, it might choose an available value by itself and set it to spi_device.bits_per_word. In order to keep align with Controller, IFX driver should make use of this value during SPI transfer, but the default one. Signed-off-by: Chen Jun jun.d.c...@intel.com Signed-off-by: channing chao...@intel.com --- drivers/tty/serial/ifx6x60.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 675d94a..5919992 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -810,7 +810,8 @@ static void ifx_spi_io(unsigned long data) ifx_dev-spi_xfer.cs_change = 0; ifx_dev-spi_xfer.speed_hz = ifx_dev-spi_dev-max_speed_hz; /* ifx_dev-spi_xfer.speed_hz = 390625; */ - ifx_dev-spi_xfer.bits_per_word = spi_bpw; + ifx_dev-spi_xfer.bits_per_word = + ifx_dev-spi_dev-bits_per_word; ifx_dev-spi_xfer.tx_buf = ifx_dev-tx_buffer; ifx_dev-spi_xfer.rx_buf = ifx_dev-rx_buffer; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] serial:ifx6x60:Delete SPI timer when shut down port
When shut down SPI port, it's possible that MRDY has been asserted and a SPI timer was activated waiting for SRDY assert, in the case, it needs to delete this timer. Signed-off-by: Chen Jun Signed-off-by: channing --- drivers/tty/serial/ifx6x60.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 5b9bc19..f5e9666 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -552,6 +552,7 @@ static void ifx_port_shutdown(struct tty_port *port) container_of(port, struct ifx_spi_device, tty_port); mrdy_set_low(ifx_dev); + del_timer(_dev->spi_timer); clear_bit(IFX_SPI_STATE_TIMER_PENDING, _dev->flags); tasklet_kill(_dev->io_work_tasklet); } -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] serial:ifx6x60:Delete SPI timer when shut down port
When shut down SPI port, it's possible that MRDY has been asserted and a SPI timer was activated waiting for SRDY assert, in the case, it needs to delete this timer. Signed-off-by: Chen Jun jun.d.c...@intel.com Signed-off-by: channing chao...@intel.com --- drivers/tty/serial/ifx6x60.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 5b9bc19..f5e9666 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -552,6 +552,7 @@ static void ifx_port_shutdown(struct tty_port *port) container_of(port, struct ifx_spi_device, tty_port); mrdy_set_low(ifx_dev); + del_timer(ifx_dev-spi_timer); clear_bit(IFX_SPI_STATE_TIMER_PENDING, ifx_dev-flags); tasklet_kill(ifx_dev-io_work_tasklet); } -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] serial:ifx6x60:Delete SPI timer when shut down port
When shut down SPI port, it's possible that MRDY has been asserted and a SPI timer was activated waiting for SRDY assert, in the case, it needs to delete this timer. Signed-off-by: Chen Jun Signed-off-by: channing --- drivers/tty/serial/ifx6x60.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 5b9bc19..f5e9666 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -552,6 +552,7 @@ static void ifx_port_shutdown(struct tty_port *port) container_of(port, struct ifx_spi_device, tty_port); mrdy_set_low(ifx_dev); + del_timer(_dev->spi_timer); clear_bit(IFX_SPI_STATE_TIMER_PENDING, _dev->flags); tasklet_kill(_dev->io_work_tasklet); } -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] serial:ifx6x60:Delete SPI timer when shut down port
On Thu, 2012-11-22 at 11:06 +, Alan Cox wrote: > > --- a/drivers/tty/serial/ifx6x60.c > > +++ b/drivers/tty/serial/ifx6x60.c > > @@ -552,7 +552,10 @@ static void ifx_port_shutdown(struct tty_port > > *port) container_of(port, struct ifx_spi_device, tty_port); > > > > mrdy_set_low(ifx_dev); > > - clear_bit(IFX_SPI_STATE_TIMER_PENDING, _dev->flags); > > + if (test_and_clear_bit(IFX_SPI_STATE_TIMER_PENDING, > > + _dev->flags)) { > > + del_timer(_dev->spi_timer); > > + } > > You don't actually need the test here as far as I can see. Providing a > timer has been initialised (init_timer) then running del_timer is safe > even if the timer is not currently queued or has completed. > > Alan Yes, thanks. I'll update it. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] serial:ifx6x60:Delete SPI timer when shut down port
When shut down SPI port, it's possible that MRDY has been asserted and a SPI timer was activated waiting for SRDY assert, in the case, it needs to delete this timer. Signed-off-by: Chen Jun Signed-off-by: channing --- drivers/tty/serial/ifx6x60.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 5b9bc19..467020b 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -552,7 +552,10 @@ static void ifx_port_shutdown(struct tty_port *port) container_of(port, struct ifx_spi_device, tty_port); mrdy_set_low(ifx_dev); - clear_bit(IFX_SPI_STATE_TIMER_PENDING, _dev->flags); + if (test_and_clear_bit(IFX_SPI_STATE_TIMER_PENDING, + _dev->flags)) { + del_timer(_dev->spi_timer); + } tasklet_kill(_dev->io_work_tasklet); } -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] serial:ifx6x60:Delete SPI timer when shut down port
When shut down SPI port, it's possible that MRDY has been asserted and a SPI timer was activated waiting for SRDY assert, in the case, it needs to delete this timer. Signed-off-by: Chen Jun jun.d.c...@intel.com Signed-off-by: channing chao...@intel.com --- drivers/tty/serial/ifx6x60.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 5b9bc19..467020b 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -552,7 +552,10 @@ static void ifx_port_shutdown(struct tty_port *port) container_of(port, struct ifx_spi_device, tty_port); mrdy_set_low(ifx_dev); - clear_bit(IFX_SPI_STATE_TIMER_PENDING, ifx_dev-flags); + if (test_and_clear_bit(IFX_SPI_STATE_TIMER_PENDING, + ifx_dev-flags)) { + del_timer(ifx_dev-spi_timer); + } tasklet_kill(ifx_dev-io_work_tasklet); } -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] serial:ifx6x60:Delete SPI timer when shut down port
On Thu, 2012-11-22 at 11:06 +, Alan Cox wrote: --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -552,7 +552,10 @@ static void ifx_port_shutdown(struct tty_port *port) container_of(port, struct ifx_spi_device, tty_port); mrdy_set_low(ifx_dev); - clear_bit(IFX_SPI_STATE_TIMER_PENDING, ifx_dev-flags); + if (test_and_clear_bit(IFX_SPI_STATE_TIMER_PENDING, + ifx_dev-flags)) { + del_timer(ifx_dev-spi_timer); + } You don't actually need the test here as far as I can see. Providing a timer has been initialised (init_timer) then running del_timer is safe even if the timer is not currently queued or has completed. Alan Yes, thanks. I'll update it. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] serial:ifx6x60:Delete SPI timer when shut down port
When shut down SPI port, it's possible that MRDY has been asserted and a SPI timer was activated waiting for SRDY assert, in the case, it needs to delete this timer. Signed-off-by: Chen Jun jun.d.c...@intel.com Signed-off-by: channing chao...@intel.com --- drivers/tty/serial/ifx6x60.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 5b9bc19..f5e9666 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -552,6 +552,7 @@ static void ifx_port_shutdown(struct tty_port *port) container_of(port, struct ifx_spi_device, tty_port); mrdy_set_low(ifx_dev); + del_timer(ifx_dev-spi_timer); clear_bit(IFX_SPI_STATE_TIMER_PENDING, ifx_dev-flags); tasklet_kill(ifx_dev-io_work_tasklet); } -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] DMA interrupt mask value should not be hard coded
In intel_mid_dma.c, when setup DMA controller, its interrupt mask value is hard coded, it's not needed because this value has already been initiated and set value according to DMA channels which are used. cc: Chen Jun Signed-off-by: channing --- drivers/dma/intel_mid_dma.c |1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c index 02b21d7..11a1a48 100644 --- a/drivers/dma/intel_mid_dma.c +++ b/drivers/dma/intel_mid_dma.c @@ -1161,7 +1161,6 @@ static int mid_setup_dma(struct pci_dev *pdev) if (0 != err) goto err_irq; } else { - dma->intr_mask = 0x03; pr_debug("MDMA:Requesting irq for DMAC2\n"); err = request_irq(pdev->irq, intel_mid_dma_interrupt2, IRQF_SHARED, "INTEL_MID_DMAC2", dma); -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] DMA interrupt mask value should not be hard coded
In intel_mid_dma.c, when setup DMA controller, its interrupt mask value is hard coded, it's not needed because this value has already been initiated and set value according to DMA channels which are used. cc: Chen Jun jun.d.c...@intel.com Signed-off-by: channing chao...@intel.com --- drivers/dma/intel_mid_dma.c |1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c index 02b21d7..11a1a48 100644 --- a/drivers/dma/intel_mid_dma.c +++ b/drivers/dma/intel_mid_dma.c @@ -1161,7 +1161,6 @@ static int mid_setup_dma(struct pci_dev *pdev) if (0 != err) goto err_irq; } else { - dma-intr_mask = 0x03; pr_debug(MDMA:Requesting irq for DMAC2\n); err = request_irq(pdev-irq, intel_mid_dma_interrupt2, IRQF_SHARED, INTEL_MID_DMAC2, dma); -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/