Skip to content

Commit 1acf6a5

Browse files
committed
Merge branch 'pci/bwctrl'
- Simplify link bandwidth controller by replacing the count of Link Bandwidth Management Status (LBMS) events with a PCI_LINK_LBMS_SEEN flag (Ilpo Järvinen) - Update the Link Speed after retraining, since the Link Speed may have changed (Ilpo Järvinen) * pci/bwctrl: PCI: Update Link Speed after retraining PCI/bwctrl: Replace lbms_count with PCI_LINK_LBMS_SEEN flag
2 parents f5b6c76 + 6ade6e8 commit 1acf6a5

File tree

5 files changed

+44
-83
lines changed

5 files changed

+44
-83
lines changed

drivers/pci/hotplug/pciehp_ctrl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ static void remove_board(struct controller *ctrl, bool safe_removal)
131131
INDICATOR_NOOP);
132132

133133
/* Don't carry LBMS indications across */
134-
pcie_reset_lbms_count(ctrl->pcie->port);
134+
pcie_reset_lbms(ctrl->pcie->port);
135135
}
136136

137137
static int pciehp_enable_slot(struct controller *ctrl);

drivers/pci/pci.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4718,6 +4718,11 @@ static int pcie_wait_for_link_status(struct pci_dev *pdev,
47184718
* @pdev: Device whose link to retrain.
47194719
* @use_lt: Use the LT bit if TRUE, or the DLLLA bit if FALSE, for status.
47204720
*
4721+
* Trigger retraining of the PCIe Link and wait for the completion of the
4722+
* retraining. As link retraining is known to asserts LBMS and may change
4723+
* the Link Speed, LBMS is cleared after the retraining and the Link Speed
4724+
* of the subordinate bus is updated.
4725+
*
47214726
* Retrain completion status is retrieved from the Link Status Register
47224727
* according to @use_lt. It is not verified whether the use of the DLLLA
47234728
* bit is valid.
@@ -4757,7 +4762,19 @@ int pcie_retrain_link(struct pci_dev *pdev, bool use_lt)
47574762
* to track link speed or width changes made by hardware itself
47584763
* in attempt to correct unreliable link operation.
47594764
*/
4760-
pcie_reset_lbms_count(pdev);
4765+
pcie_reset_lbms(pdev);
4766+
4767+
/*
4768+
* Ensure the Link Speed updates after retraining in case the Link
4769+
* Speed was changed because of the retraining. While the bwctrl's
4770+
* IRQ handler normally picks up the new Link Speed, clearing LBMS
4771+
* races with the IRQ handler reading the Link Status register and
4772+
* can result in the handler returning early without updating the
4773+
* Link Speed.
4774+
*/
4775+
if (pdev->subordinate)
4776+
pcie_update_link_speed(pdev->subordinate);
4777+
47614778
return rc;
47624779
}
47634780

drivers/pci/pci.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
557557
#define PCI_DPC_RECOVERED 1
558558
#define PCI_DPC_RECOVERING 2
559559
#define PCI_DEV_REMOVED 3
560+
#define PCI_LINK_LBMS_SEEN 6
560561

561562
static inline void pci_dev_assign_added(struct pci_dev *dev)
562563
{
@@ -828,14 +829,9 @@ static inline void pcie_ecrc_get_policy(char *str) { }
828829
#endif
829830

830831
#ifdef CONFIG_PCIEPORTBUS
831-
void pcie_reset_lbms_count(struct pci_dev *port);
832-
int pcie_lbms_count(struct pci_dev *port, unsigned long *val);
832+
void pcie_reset_lbms(struct pci_dev *port);
833833
#else
834-
static inline void pcie_reset_lbms_count(struct pci_dev *port) {}
835-
static inline int pcie_lbms_count(struct pci_dev *port, unsigned long *val)
836-
{
837-
return -EOPNOTSUPP;
838-
}
834+
static inline void pcie_reset_lbms(struct pci_dev *port) {}
839835
#endif
840836

841837
struct pci_dev_reset_methods {

drivers/pci/pcie/bwctrl.c

Lines changed: 19 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,14 @@
3838
/**
3939
* struct pcie_bwctrl_data - PCIe bandwidth controller
4040
* @set_speed_mutex: Serializes link speed changes
41-
* @lbms_count: Count for LBMS (since last reset)
4241
* @cdev: Thermal cooling device associated with the port
4342
*/
4443
struct pcie_bwctrl_data {
4544
struct mutex set_speed_mutex;
46-
atomic_t lbms_count;
4745
struct thermal_cooling_device *cdev;
4846
};
4947

50-
/*
51-
* Prevent port removal during LBMS count accessors and Link Speed changes.
52-
*
53-
* These have to be differentiated because pcie_bwctrl_change_speed() calls
54-
* pcie_retrain_link() which uses LBMS count reset accessor on success
55-
* (using just one rwsem triggers "possible recursive locking detected"
56-
* warning).
57-
*/
58-
static DECLARE_RWSEM(pcie_bwctrl_lbms_rwsem);
48+
/* Prevent port removal during Link Speed changes. */
5949
static DECLARE_RWSEM(pcie_bwctrl_setspeed_rwsem);
6050

6151
static bool pcie_valid_speed(enum pci_bus_speed speed)
@@ -127,18 +117,7 @@ static int pcie_bwctrl_change_speed(struct pci_dev *port, u16 target_speed, bool
127117
if (ret != PCIBIOS_SUCCESSFUL)
128118
return pcibios_err_to_errno(ret);
129119

130-
ret = pcie_retrain_link(port, use_lt);
131-
if (ret < 0)
132-
return ret;
133-
134-
/*
135-
* Ensure link speed updates also with platforms that have problems
136-
* with notifications.
137-
*/
138-
if (port->subordinate)
139-
pcie_update_link_speed(port->subordinate);
140-
141-
return 0;
120+
return pcie_retrain_link(port, use_lt);
142121
}
143122

144123
/**
@@ -202,15 +181,14 @@ int pcie_set_target_speed(struct pci_dev *port, enum pci_bus_speed speed_req,
202181

203182
static void pcie_bwnotif_enable(struct pcie_device *srv)
204183
{
205-
struct pcie_bwctrl_data *data = srv->port->link_bwctrl;
206184
struct pci_dev *port = srv->port;
207185
u16 link_status;
208186
int ret;
209187

210-
/* Count LBMS seen so far as one */
188+
/* Note if LBMS has been seen so far */
211189
ret = pcie_capability_read_word(port, PCI_EXP_LNKSTA, &link_status);
212190
if (ret == PCIBIOS_SUCCESSFUL && link_status & PCI_EXP_LNKSTA_LBMS)
213-
atomic_inc(&data->lbms_count);
191+
set_bit(PCI_LINK_LBMS_SEEN, &port->priv_flags);
214192

215193
pcie_capability_set_word(port, PCI_EXP_LNKCTL,
216194
PCI_EXP_LNKCTL_LBMIE | PCI_EXP_LNKCTL_LABIE);
@@ -233,7 +211,6 @@ static void pcie_bwnotif_disable(struct pci_dev *port)
233211
static irqreturn_t pcie_bwnotif_irq(int irq, void *context)
234212
{
235213
struct pcie_device *srv = context;
236-
struct pcie_bwctrl_data *data = srv->port->link_bwctrl;
237214
struct pci_dev *port = srv->port;
238215
u16 link_status, events;
239216
int ret;
@@ -247,7 +224,7 @@ static irqreturn_t pcie_bwnotif_irq(int irq, void *context)
247224
return IRQ_NONE;
248225

249226
if (events & PCI_EXP_LNKSTA_LBMS)
250-
atomic_inc(&data->lbms_count);
227+
set_bit(PCI_LINK_LBMS_SEEN, &port->priv_flags);
251228

252229
pcie_capability_write_word(port, PCI_EXP_LNKSTA, events);
253230

@@ -262,31 +239,10 @@ static irqreturn_t pcie_bwnotif_irq(int irq, void *context)
262239
return IRQ_HANDLED;
263240
}
264241

265-
void pcie_reset_lbms_count(struct pci_dev *port)
242+
void pcie_reset_lbms(struct pci_dev *port)
266243
{
267-
struct pcie_bwctrl_data *data;
268-
269-
guard(rwsem_read)(&pcie_bwctrl_lbms_rwsem);
270-
data = port->link_bwctrl;
271-
if (data)
272-
atomic_set(&data->lbms_count, 0);
273-
else
274-
pcie_capability_write_word(port, PCI_EXP_LNKSTA,
275-
PCI_EXP_LNKSTA_LBMS);
276-
}
277-
278-
int pcie_lbms_count(struct pci_dev *port, unsigned long *val)
279-
{
280-
struct pcie_bwctrl_data *data;
281-
282-
guard(rwsem_read)(&pcie_bwctrl_lbms_rwsem);
283-
data = port->link_bwctrl;
284-
if (!data)
285-
return -ENOTTY;
286-
287-
*val = atomic_read(&data->lbms_count);
288-
289-
return 0;
244+
clear_bit(PCI_LINK_LBMS_SEEN, &port->priv_flags);
245+
pcie_capability_write_word(port, PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_LBMS);
290246
}
291247

292248
static int pcie_bwnotif_probe(struct pcie_device *srv)
@@ -308,18 +264,16 @@ static int pcie_bwnotif_probe(struct pcie_device *srv)
308264
return ret;
309265

310266
scoped_guard(rwsem_write, &pcie_bwctrl_setspeed_rwsem) {
311-
scoped_guard(rwsem_write, &pcie_bwctrl_lbms_rwsem) {
312-
port->link_bwctrl = data;
313-
314-
ret = request_irq(srv->irq, pcie_bwnotif_irq,
315-
IRQF_SHARED, "PCIe bwctrl", srv);
316-
if (ret) {
317-
port->link_bwctrl = NULL;
318-
return ret;
319-
}
267+
port->link_bwctrl = data;
320268

321-
pcie_bwnotif_enable(srv);
269+
ret = request_irq(srv->irq, pcie_bwnotif_irq,
270+
IRQF_SHARED, "PCIe bwctrl", srv);
271+
if (ret) {
272+
port->link_bwctrl = NULL;
273+
return ret;
322274
}
275+
276+
pcie_bwnotif_enable(srv);
323277
}
324278

325279
pci_dbg(port, "enabled with IRQ %d\n", srv->irq);
@@ -339,13 +293,11 @@ static void pcie_bwnotif_remove(struct pcie_device *srv)
339293
pcie_cooling_device_unregister(data->cdev);
340294

341295
scoped_guard(rwsem_write, &pcie_bwctrl_setspeed_rwsem) {
342-
scoped_guard(rwsem_write, &pcie_bwctrl_lbms_rwsem) {
343-
pcie_bwnotif_disable(srv->port);
296+
pcie_bwnotif_disable(srv->port);
344297

345-
free_irq(srv->irq, srv);
298+
free_irq(srv->irq, srv);
346299

347-
srv->port->link_bwctrl = NULL;
348-
}
300+
srv->port->link_bwctrl = NULL;
349301
}
350302
}
351303

drivers/pci/quirks.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,10 @@
3838

3939
static bool pcie_lbms_seen(struct pci_dev *dev, u16 lnksta)
4040
{
41-
unsigned long count;
42-
int ret;
43-
44-
ret = pcie_lbms_count(dev, &count);
45-
if (ret < 0)
46-
return lnksta & PCI_EXP_LNKSTA_LBMS;
41+
if (test_bit(PCI_LINK_LBMS_SEEN, &dev->priv_flags))
42+
return true;
4743

48-
return count > 0;
44+
return lnksta & PCI_EXP_LNKSTA_LBMS;
4945
}
5046

5147
/*

0 commit comments

Comments
 (0)