History

atm: nicstar: Replace in_interrupt() usage

push_scqe() uses in_interrupt() to figure out if it is allowed to sleep. The usage of in_interrupt() in drivers is phased out and Linus clearly requested that code which changes behaviour depending on context should either be separated or the context be conveyed in an argument passed by the caller, which usually knows the context. Aside of that in_interrupt() is not correct as it does not catch preempt disabled regions which neither can sleep. ns_send() (the only caller of push_scqe()) has the following callers: - vcc_sendmsg() used as proto_ops::sendmsg is expected to be invoked in preemtible context. -> vcc->dev->ops->send() (ns_send()) - atm_vcc::send via atmdev_ops::send either directly (pointer copied by atm_init_aal34() or atm_init_aal5()) or via atm_send_aal0(). This is invoked by drivers (like br2684, clip, pppoatm, ...) which are called from net_device_ops::ndo_start_xmit with BH disabled. Add atmdev_ops::send_bh which is used by callers from BH context (atm_send_aal*()) and if this callback missing then ::send is used instead. Implement this callback in nicstar and use it to replace in_interrupt().

Sebastian Andrzej Siewior committed 5 years ago

Commit f2bcc2f1 parent 030946f3 files · +29 −8Browse files

Unified · Split

3 files
  1. drivers/atm/nicstar.c +18 −6
  2. include/linux/atmdev.h +1 −0
  3. net/atm/raw.c +10 −2
drivers/atm/nicstar.c+18−6
@@ -130,8 +130,9 @@ static int ns_open(struct atm_vcc *vcc); · 129 unmodified lines
130static void ns_close(struct atm_vcc *vcc);130static void ns_close(struct atm_vcc *vcc);
131static void fill_tst(ns_dev * card, int n, vc_map * vc);131static void fill_tst(ns_dev * card, int n, vc_map * vc);
132static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb);132static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb);
133static int ns_send_bh(struct atm_vcc *vcc, struct sk_buff *skb);
133static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,134static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
134 struct sk_buff *skb);135 struct sk_buff *skb, bool may_sleep);
135static void process_tsq(ns_dev * card);136static void process_tsq(ns_dev * card);
136static void drain_scq(ns_dev * card, scq_info * scq, int pos);137static void drain_scq(ns_dev * card, scq_info * scq, int pos);
137static void process_rsq(ns_dev * card);138static void process_rsq(ns_dev * card);
@@ -160,6 +161,7 @@ static const struct atmdev_ops atm_ops = { · 22 unmodified lines
160 .close = ns_close,161 .close = ns_close,
161 .ioctl = ns_ioctl,162 .ioctl = ns_ioctl,
162 .send = ns_send,163 .send = ns_send,
164 .send_bh = ns_send_bh,
163 .phy_put = ns_phy_put,165 .phy_put = ns_phy_put,
164 .phy_get = ns_phy_get,166 .phy_get = ns_phy_get,
165 .proc_read = ns_proc_read,167 .proc_read = ns_proc_read,
@@ -1620,7 +1622,7 @@ static void fill_tst(ns_dev * card, int n, vc_map * vc) · 1454 unmodified lines
1620 card->tst_addr = new_tst;1622 card->tst_addr = new_tst;
1621}1623}
1622 1624
1623static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb)1625static int _ns_send(struct atm_vcc *vcc, struct sk_buff *skb, bool may_sleep)
1624{1626{
1625 ns_dev *card;1627 ns_dev *card;
1626 vc_map *vc;1628 vc_map *vc;
@@ -1704,7 +1706,7 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) · 77 unmodified lines
1704 scq = card->scq0;1706 scq = card->scq0;
1705 }1707 }
1706 1708
1707 if (push_scqe(card, vc, scq, &scqe, skb) != 0) {1709 if (push_scqe(card, vc, scq, &scqe, skb, may_sleep) != 0) {
1708 atomic_inc(&vcc->stats->tx_err);1710 atomic_inc(&vcc->stats->tx_err);
1709 dev_kfree_skb_any(skb);1711 dev_kfree_skb_any(skb);
1710 return -EIO;1712 return -EIO;
@@ -1714,8 +1716,18 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) · 3 unmodified lines
1714 return 0;1716 return 0;
1715}1717}
1716 1718
1719static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb)
1720{
1721 return _ns_send(vcc, skb, true);
1722}
1723
1724static int ns_send_bh(struct atm_vcc *vcc, struct sk_buff *skb)
1725{
1726 return _ns_send(vcc, skb, false);
1727}
1728
1717static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,1729static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
1718 struct sk_buff *skb)1730 struct sk_buff *skb, bool may_sleep)
1719{1731{
1720 unsigned long flags;1732 unsigned long flags;
1721 ns_scqe tsr;1733 ns_scqe tsr;
@@ -1726,7 +1738,7 @@ static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd, · 4 unmodified lines
1726 1738
1727 spin_lock_irqsave(&scq->lock, flags);1739 spin_lock_irqsave(&scq->lock, flags);
1728 while (scq->tail == scq->next) {1740 while (scq->tail == scq->next) {
1729 if (in_interrupt()) {1741 if (!may_sleep) {
1730 spin_unlock_irqrestore(&scq->lock, flags);1742 spin_unlock_irqrestore(&scq->lock, flags);
1731 printk("nicstar%d: Error pushing TBD.\n", card->index);1743 printk("nicstar%d: Error pushing TBD.\n", card->index);
1732 return 1;1744 return 1;
@@ -1771,7 +1783,7 @@ static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd, · 38 unmodified lines
1771 int has_run = 0;1783 int has_run = 0;
1772 1784
1773 while (scq->tail == scq->next) {1785 while (scq->tail == scq->next) {
1774 if (in_interrupt()) {1786 if (!may_sleep) {
1775 data = scq_virt_to_bus(scq, scq->next);1787 data = scq_virt_to_bus(scq, scq->next);
1776 ns_write_sram(card, scq->scd, &data, 1);1788 ns_write_sram(card, scq->scd, &data, 1);
1777 spin_unlock_irqrestore(&scq->lock, flags);1789 spin_unlock_irqrestore(&scq->lock, flags);
include/linux/atmdev.h+1−0
@@ -186,6 +186,7 @@ struct atmdev_ops { /* only send is required */ · 185 unmodified lines
186 void __user *arg);186 void __user *arg);
187#endif187#endif
188 int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);188 int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
189 int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb);
189 int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags);190 int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags);
190 void (*phy_put)(struct atm_dev *dev,unsigned char value,191 void (*phy_put)(struct atm_dev *dev,unsigned char value,
191 unsigned long addr);192 unsigned long addr);
net/atm/raw.c+10−2
@@ -54,6 +54,8 @@ static int atm_send_aal0(struct atm_vcc *vcc, struct sk_buff *skb) · 53 unmodified lines
54 kfree_skb(skb);54 kfree_skb(skb);
55 return -EADDRNOTAVAIL;55 return -EADDRNOTAVAIL;
56 }56 }
57 if (vcc->dev->ops->send_bh)
58 return vcc->dev->ops->send_bh(vcc, skb);
57 return vcc->dev->ops->send(vcc, skb);59 return vcc->dev->ops->send(vcc, skb);
58}60}
59 61
@@ -71,7 +73,10 @@ int atm_init_aal34(struct atm_vcc *vcc) · 11 unmodified lines
71 vcc->push = atm_push_raw;73 vcc->push = atm_push_raw;
72 vcc->pop = atm_pop_raw;74 vcc->pop = atm_pop_raw;
73 vcc->push_oam = NULL;75 vcc->push_oam = NULL;
74 vcc->send = vcc->dev->ops->send;76 if (vcc->dev->ops->send_bh)
77 vcc->send = vcc->dev->ops->send_bh;
78 else
79 vcc->send = vcc->dev->ops->send;
75 return 0;80 return 0;
76}81}
77 82
@@ -80,7 +85,10 @@ int atm_init_aal5(struct atm_vcc *vcc) · 2 unmodified lines
80 vcc->push = atm_push_raw;85 vcc->push = atm_push_raw;
81 vcc->pop = atm_pop_raw;86 vcc->pop = atm_pop_raw;
82 vcc->push_oam = NULL;87 vcc->push_oam = NULL;
83 vcc->send = vcc->dev->ops->send;88 if (vcc->dev->ops->send_bh)
89 vcc->send = vcc->dev->ops->send_bh;
90 else
91 vcc->send = vcc->dev->ops->send;
84 return 0;92 return 0;
85}93}
86EXPORT_SYMBOL(atm_init_aal5);94EXPORT_SYMBOL(atm_init_aal5);