aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Mason <jon.mason@intel.com>2013-04-18 20:59:44 -0400
committerJon Mason <jon.mason@intel.com>2013-11-20 11:57:34 -0500
commite8aeb60c389c2aa48d345bcf717f8cb7edf67680 (patch)
tree3610f55a47e8f0bc722397ec8063c9a4f4091f9b
parent78958433db077b339f3a039890148561086574e4 (diff)
NTB: Disable interrupts and poll under high load
Disable interrupts and poll under high load Signed-off-by: Jon Mason <jon.mason@intel.com>
-rw-r--r--drivers/ntb/ntb_hw.c42
-rw-r--r--drivers/ntb/ntb_hw.h7
-rw-r--r--drivers/ntb/ntb_transport.c25
3 files changed, 48 insertions, 26 deletions
diff --git a/drivers/ntb/ntb_hw.c b/drivers/ntb/ntb_hw.c
index 80505aeecf9e..170e8e60cdb7 100644
--- a/drivers/ntb/ntb_hw.c
+++ b/drivers/ntb/ntb_hw.c
@@ -141,6 +141,24 @@ void ntb_unregister_event_callback(struct ntb_device *ndev)
141 ndev->event_cb = NULL; 141 ndev->event_cb = NULL;
142} 142}
143 143
144static void ntb_irq_work(unsigned long data)
145{
146 struct ntb_db_cb *db_cb = (struct ntb_db_cb *)data;
147 int rc;
148
149 rc = db_cb->callback(db_cb->data, db_cb->db_num);
150 if (rc)
151 tasklet_schedule(&db_cb->irq_work);
152 else {
153 struct ntb_device *ndev = db_cb->ndev;
154 unsigned long mask;
155
156 mask = readw(ndev->reg_ofs.ldb_mask);
157 clear_bit(db_cb->db_num * ndev->bits_per_vector, &mask);
158 writew(mask, ndev->reg_ofs.ldb_mask);
159 }
160}
161
144/** 162/**
145 * ntb_register_db_callback() - register a callback for doorbell interrupt 163 * ntb_register_db_callback() - register a callback for doorbell interrupt
146 * @ndev: pointer to ntb_device instance 164 * @ndev: pointer to ntb_device instance
@@ -155,7 +173,7 @@ void ntb_unregister_event_callback(struct ntb_device *ndev)
155 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 173 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
156 */ 174 */
157int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx, 175int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx,
158 void *data, void (*func)(void *data, int db_num)) 176 void *data, int (*func)(void *data, int db_num))
159{ 177{
160 unsigned long mask; 178 unsigned long mask;
161 179
@@ -166,6 +184,10 @@ int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx,
166 184
167 ndev->db_cb[idx].callback = func; 185 ndev->db_cb[idx].callback = func;
168 ndev->db_cb[idx].data = data; 186 ndev->db_cb[idx].data = data;
187 ndev->db_cb[idx].ndev = ndev;
188
189 tasklet_init(&ndev->db_cb[idx].irq_work, ntb_irq_work,
190 (unsigned long) &ndev->db_cb[idx]);
169 191
170 /* unmask interrupt */ 192 /* unmask interrupt */
171 mask = readw(ndev->reg_ofs.ldb_mask); 193 mask = readw(ndev->reg_ofs.ldb_mask);
@@ -194,6 +216,8 @@ void ntb_unregister_db_callback(struct ntb_device *ndev, unsigned int idx)
194 set_bit(idx * ndev->bits_per_vector, &mask); 216 set_bit(idx * ndev->bits_per_vector, &mask);
195 writew(mask, ndev->reg_ofs.ldb_mask); 217 writew(mask, ndev->reg_ofs.ldb_mask);
196 218
219 tasklet_disable(&ndev->db_cb[idx].irq_work);
220
197 ndev->db_cb[idx].callback = NULL; 221 ndev->db_cb[idx].callback = NULL;
198} 222}
199 223
@@ -955,12 +979,16 @@ static irqreturn_t bwd_callback_msix_irq(int irq, void *data)
955{ 979{
956 struct ntb_db_cb *db_cb = data; 980 struct ntb_db_cb *db_cb = data;
957 struct ntb_device *ndev = db_cb->ndev; 981 struct ntb_device *ndev = db_cb->ndev;
982 unsigned long mask;
958 983
959 dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq, 984 dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq,
960 db_cb->db_num); 985 db_cb->db_num);
961 986
962 if (db_cb->callback) 987 mask = readw(ndev->reg_ofs.ldb_mask);
963 db_cb->callback(db_cb->data, db_cb->db_num); 988 set_bit(db_cb->db_num * ndev->bits_per_vector, &mask);
989 writew(mask, ndev->reg_ofs.ldb_mask);
990
991 tasklet_schedule(&db_cb->irq_work);
964 992
965 /* No need to check for the specific HB irq, any interrupt means 993 /* No need to check for the specific HB irq, any interrupt means
966 * we're connected. 994 * we're connected.
@@ -976,12 +1004,16 @@ static irqreturn_t xeon_callback_msix_irq(int irq, void *data)
976{ 1004{
977 struct ntb_db_cb *db_cb = data; 1005 struct ntb_db_cb *db_cb = data;
978 struct ntb_device *ndev = db_cb->ndev; 1006 struct ntb_device *ndev = db_cb->ndev;
1007 unsigned long mask;
979 1008
980 dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq, 1009 dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq,
981 db_cb->db_num); 1010 db_cb->db_num);
982 1011
983 if (db_cb->callback) 1012 mask = readw(ndev->reg_ofs.ldb_mask);
984 db_cb->callback(db_cb->data, db_cb->db_num); 1013 set_bit(db_cb->db_num * ndev->bits_per_vector, &mask);
1014 writew(mask, ndev->reg_ofs.ldb_mask);
1015
1016 tasklet_schedule(&db_cb->irq_work);
985 1017
986 /* On Sandybridge, there are 16 bits in the interrupt register 1018 /* On Sandybridge, there are 16 bits in the interrupt register
987 * but only 4 vectors. So, 5 bits are assigned to the first 3 1019 * but only 4 vectors. So, 5 bits are assigned to the first 3
diff --git a/drivers/ntb/ntb_hw.h b/drivers/ntb/ntb_hw.h
index 0a31cedae7d4..bbdb7edca10c 100644
--- a/drivers/ntb/ntb_hw.h
+++ b/drivers/ntb/ntb_hw.h
@@ -106,10 +106,11 @@ struct ntb_mw {
106}; 106};
107 107
108struct ntb_db_cb { 108struct ntb_db_cb {
109 void (*callback) (void *data, int db_num); 109 int (*callback)(void *data, int db_num);
110 unsigned int db_num; 110 unsigned int db_num;
111 void *data; 111 void *data;
112 struct ntb_device *ndev; 112 struct ntb_device *ndev;
113 struct tasklet_struct irq_work;
113}; 114};
114 115
115struct ntb_device { 116struct ntb_device {
@@ -228,8 +229,8 @@ struct ntb_device *ntb_register_transport(struct pci_dev *pdev,
228void ntb_unregister_transport(struct ntb_device *ndev); 229void ntb_unregister_transport(struct ntb_device *ndev);
229void ntb_set_mw_addr(struct ntb_device *ndev, unsigned int mw, u64 addr); 230void ntb_set_mw_addr(struct ntb_device *ndev, unsigned int mw, u64 addr);
230int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx, 231int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx,
231 void *data, void (*db_cb_func) (void *data, 232 void *data, int (*db_cb_func)(void *data,
232 int db_num)); 233 int db_num));
233void ntb_unregister_db_callback(struct ntb_device *ndev, unsigned int idx); 234void ntb_unregister_db_callback(struct ntb_device *ndev, unsigned int idx);
234int ntb_register_event_callback(struct ntb_device *ndev, 235int ntb_register_event_callback(struct ntb_device *ndev,
235 void (*event_cb_func) (void *handle, 236 void (*event_cb_func) (void *handle,
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 172501d47600..676937bd679c 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -119,7 +119,6 @@ struct ntb_transport_qp {
119 119
120 void (*rx_handler) (struct ntb_transport_qp *qp, void *qp_data, 120 void (*rx_handler) (struct ntb_transport_qp *qp, void *qp_data,
121 void *data, int len); 121 void *data, int len);
122 struct tasklet_struct rx_work;
123 struct list_head rx_pend_q; 122 struct list_head rx_pend_q;
124 struct list_head rx_free_q; 123 struct list_head rx_free_q;
125 spinlock_t ntb_rx_pend_q_lock; 124 spinlock_t ntb_rx_pend_q_lock;
@@ -1188,11 +1187,14 @@ err:
1188 goto out; 1187 goto out;
1189} 1188}
1190 1189
1191static void ntb_transport_rx(unsigned long data) 1190static int ntb_transport_rxc_db(void *data, int db_num)
1192{ 1191{
1193 struct ntb_transport_qp *qp = (struct ntb_transport_qp *)data; 1192 struct ntb_transport_qp *qp = data;
1194 int rc, i; 1193 int rc, i;
1195 1194
1195 dev_dbg(&ntb_query_pdev(qp->ndev)->dev, "%s: doorbell %d received\n",
1196 __func__, db_num);
1197
1196 /* Limit the number of packets processed in a single interrupt to 1198 /* Limit the number of packets processed in a single interrupt to
1197 * provide fairness to others 1199 * provide fairness to others
1198 */ 1200 */
@@ -1204,16 +1206,8 @@ static void ntb_transport_rx(unsigned long data)
1204 1206
1205 if (qp->dma_chan) 1207 if (qp->dma_chan)
1206 dma_async_issue_pending(qp->dma_chan); 1208 dma_async_issue_pending(qp->dma_chan);
1207}
1208
1209static void ntb_transport_rxc_db(void *data, int db_num)
1210{
1211 struct ntb_transport_qp *qp = data;
1212 1209
1213 dev_dbg(&ntb_query_pdev(qp->ndev)->dev, "%s: doorbell %d received\n", 1210 return i;
1214 __func__, db_num);
1215
1216 tasklet_schedule(&qp->rx_work);
1217} 1211}
1218 1212
1219static void ntb_tx_copy_callback(void *data) 1213static void ntb_tx_copy_callback(void *data)
@@ -1446,19 +1440,15 @@ ntb_transport_create_queue(void *data, struct pci_dev *pdev,
1446 &qp->tx_free_q); 1440 &qp->tx_free_q);
1447 } 1441 }
1448 1442
1449 tasklet_init(&qp->rx_work, ntb_transport_rx, (unsigned long) qp);
1450
1451 rc = ntb_register_db_callback(qp->ndev, free_queue, qp, 1443 rc = ntb_register_db_callback(qp->ndev, free_queue, qp,
1452 ntb_transport_rxc_db); 1444 ntb_transport_rxc_db);
1453 if (rc) 1445 if (rc)
1454 goto err3; 1446 goto err2;
1455 1447
1456 dev_info(&pdev->dev, "NTB Transport QP %d created\n", qp->qp_num); 1448 dev_info(&pdev->dev, "NTB Transport QP %d created\n", qp->qp_num);
1457 1449
1458 return qp; 1450 return qp;
1459 1451
1460err3:
1461 tasklet_disable(&qp->rx_work);
1462err2: 1452err2:
1463 while ((entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q))) 1453 while ((entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q)))
1464 kfree(entry); 1454 kfree(entry);
@@ -1505,7 +1495,6 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
1505 } 1495 }
1506 1496
1507 ntb_unregister_db_callback(qp->ndev, qp->qp_num); 1497 ntb_unregister_db_callback(qp->ndev, qp->qp_num);
1508 tasklet_disable(&qp->rx_work);
1509 1498
1510 cancel_delayed_work_sync(&qp->link_work); 1499 cancel_delayed_work_sync(&qp->link_work);
1511 1500