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
130130 static void ns_close(struct atm_vcc *vcc);
131131 static void fill_tst(ns_dev * card, int n, vc_map * vc);
132132 static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb);
133+static int ns_send_bh(struct atm_vcc *vcc, struct sk_buff *skb);
133134 static 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);
135136 static void process_tsq(ns_dev * card);
136137 static void drain_scq(ns_dev * card, scq_info * scq, int pos);
137138 static void process_rsq(ns_dev * card);
@@ -160,6 +161,7 @@ static const struct atmdev_ops atm_ops = { · 22 unmodified lines
160161 .close = ns_close,
161162 .ioctl = ns_ioctl,
162163 .send = ns_send,
164+ .send_bh = ns_send_bh,
163165 .phy_put = ns_phy_put,
164166 .phy_get = ns_phy_get,
165167 .proc_read = ns_proc_read,
@@ -1620,7 +1622,7 @@ static void fill_tst(ns_dev * card, int n, vc_map * vc) · 1454 unmodified lines
16201622 card->tst_addr = new_tst;
16211623 }
16221624
1623−static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb)
1625+static int _ns_send(struct atm_vcc *vcc, struct sk_buff *skb, bool may_sleep)
16241626 {
16251627 ns_dev *card;
16261628 vc_map *vc;
@@ -1704,7 +1706,7 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) · 77 unmodified lines
17041706 scq = card->scq0;
17051707 }
17061708
1707− if (push_scqe(card, vc, scq, &scqe, skb) != 0) {
1709+ if (push_scqe(card, vc, scq, &scqe, skb, may_sleep) != 0) {
17081710 atomic_inc(&vcc->stats->tx_err);
17091711 dev_kfree_skb_any(skb);
17101712 return -EIO;
@@ -1714,8 +1716,18 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) · 3 unmodified lines
17141716 return 0;
17151717 }
17161718
1719+static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb)
1720+{
1721+ return _ns_send(vcc, skb, true);
1722+}
1723+
1724+static int ns_send_bh(struct atm_vcc *vcc, struct sk_buff *skb)
1725+{
1726+ return _ns_send(vcc, skb, false);
1727+}
1728+
17171729 static 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)
17191731 {
17201732 unsigned long flags;
17211733 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
17261738
17271739 spin_lock_irqsave(&scq->lock, flags);
17281740 while (scq->tail == scq->next) {
1729− if (in_interrupt()) {
1741+ if (!may_sleep) {
17301742 spin_unlock_irqrestore(&scq->lock, flags);
17311743 printk("nicstar%d: Error pushing TBD.\n", card->index);
17321744 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
17711783 int has_run = 0;
17721784
17731785 while (scq->tail == scq->next) {
1774− if (in_interrupt()) {
1786+ if (!may_sleep) {
17751787 data = scq_virt_to_bus(scq, scq->next);
17761788 ns_write_sram(card, scq->scd, &data, 1);
17771789 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
186186 void __user *arg);
187187 #endif
188188 int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
189+ int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb);
189190 int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags);
190191 void (*phy_put)(struct atm_dev *dev,unsigned char value,
191192 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
5454 kfree_skb(skb);
5555 return -EADDRNOTAVAIL;
5656 }
57+ if (vcc->dev->ops->send_bh)
58+ return vcc->dev->ops->send_bh(vcc, skb);
5759 return vcc->dev->ops->send(vcc, skb);
5860 }
5961
@@ -71,7 +73,10 @@ int atm_init_aal34(struct atm_vcc *vcc) · 11 unmodified lines
7173 vcc->push = atm_push_raw;
7274 vcc->pop = atm_pop_raw;
7375 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;
7580 return 0;
7681 }
7782
@@ -80,7 +85,10 @@ int atm_init_aal5(struct atm_vcc *vcc) · 2 unmodified lines
8085 vcc->push = atm_push_raw;
8186 vcc->pop = atm_pop_raw;
8287 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;
8492 return 0;
8593 }
8694 EXPORT_SYMBOL(atm_init_aal5);