diff options
author | Divy Le Ray <divy@chelsio.com> | 2008-12-16 04:09:39 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-16 04:09:39 -0500 |
commit | 82ad33297410c1af8e993210da76e114a4c1670d (patch) | |
tree | 63044ca2d003efc85461a5e0943a175dbc960742 /drivers | |
parent | 89c88b16f12e9df9ac39418638f267ec3b36a6c6 (diff) |
cxgb3: Add multiple Tx queue support.
Implement NIC Tx multiqueue.
Bump up driver version.
Signed-off-by: Divy Le Ray <divy@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/cxgb3/adapter.h | 4 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 11 | ||||
-rw-r--r-- | drivers/net/cxgb3/sge.c | 30 | ||||
-rw-r--r-- | drivers/net/cxgb3/version.h | 2 |
4 files changed, 31 insertions, 16 deletions
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index bc8e2413abd2..c190a69c4d71 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h | |||
@@ -196,6 +196,7 @@ struct sge_qset { /* an SGE queue set */ | |||
196 | int lro_frag_len; | 196 | int lro_frag_len; |
197 | void *lro_va; | 197 | void *lro_va; |
198 | struct net_device *netdev; | 198 | struct net_device *netdev; |
199 | struct netdev_queue *tx_q; /* associated netdev TX queue */ | ||
199 | unsigned long txq_stopped; /* which Tx queues are stopped */ | 200 | unsigned long txq_stopped; /* which Tx queues are stopped */ |
200 | struct timer_list tx_reclaim_timer; /* reclaims TX buffers */ | 201 | struct timer_list tx_reclaim_timer; /* reclaims TX buffers */ |
201 | unsigned long port_stats[SGE_PSTAT_MAX]; | 202 | unsigned long port_stats[SGE_PSTAT_MAX]; |
@@ -294,7 +295,8 @@ int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb); | |||
294 | void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p); | 295 | void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p); |
295 | int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | 296 | int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, |
296 | int irq_vec_idx, const struct qset_params *p, | 297 | int irq_vec_idx, const struct qset_params *p, |
297 | int ntxq, struct net_device *dev); | 298 | int ntxq, struct net_device *dev, |
299 | struct netdev_queue *netdevq); | ||
298 | int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx, | 300 | int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx, |
299 | unsigned char *data); | 301 | unsigned char *data); |
300 | irqreturn_t t3_sge_intr_msix(int irq, void *cookie); | 302 | irqreturn_t t3_sge_intr_msix(int irq, void *cookie); |
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 46c114e928a0..9e8727c5eced 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
@@ -550,7 +550,8 @@ static int setup_sge_qsets(struct adapter *adap) | |||
550 | err = t3_sge_alloc_qset(adap, qset_idx, 1, | 550 | err = t3_sge_alloc_qset(adap, qset_idx, 1, |
551 | (adap->flags & USING_MSIX) ? qset_idx + 1 : | 551 | (adap->flags & USING_MSIX) ? qset_idx + 1 : |
552 | irq_idx, | 552 | irq_idx, |
553 | &adap->params.sge.qset[qset_idx], ntxq, dev); | 553 | &adap->params.sge.qset[qset_idx], ntxq, dev, |
554 | netdev_get_tx_queue(dev, j)); | ||
554 | if (err) { | 555 | if (err) { |
555 | t3_stop_sge_timers(adap); | 556 | t3_stop_sge_timers(adap); |
556 | t3_free_sge_resources(adap); | 557 | t3_free_sge_resources(adap); |
@@ -1165,9 +1166,10 @@ static int cxgb_open(struct net_device *dev) | |||
1165 | "Could not initialize offload capabilities\n"); | 1166 | "Could not initialize offload capabilities\n"); |
1166 | } | 1167 | } |
1167 | 1168 | ||
1169 | dev->real_num_tx_queues = pi->nqsets; | ||
1168 | link_start(dev); | 1170 | link_start(dev); |
1169 | t3_port_intr_enable(adapter, pi->port_id); | 1171 | t3_port_intr_enable(adapter, pi->port_id); |
1170 | netif_start_queue(dev); | 1172 | netif_tx_start_all_queues(dev); |
1171 | if (!other_ports) | 1173 | if (!other_ports) |
1172 | schedule_chk_task(adapter); | 1174 | schedule_chk_task(adapter); |
1173 | 1175 | ||
@@ -1180,7 +1182,7 @@ static int cxgb_close(struct net_device *dev) | |||
1180 | struct adapter *adapter = pi->adapter; | 1182 | struct adapter *adapter = pi->adapter; |
1181 | 1183 | ||
1182 | t3_port_intr_disable(adapter, pi->port_id); | 1184 | t3_port_intr_disable(adapter, pi->port_id); |
1183 | netif_stop_queue(dev); | 1185 | netif_tx_stop_all_queues(dev); |
1184 | pi->phy.ops->power_down(&pi->phy, 1); | 1186 | pi->phy.ops->power_down(&pi->phy, 1); |
1185 | netif_carrier_off(dev); | 1187 | netif_carrier_off(dev); |
1186 | t3_mac_disable(&pi->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX); | 1188 | t3_mac_disable(&pi->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX); |
@@ -2932,7 +2934,7 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
2932 | for (i = 0; i < ai->nports; ++i) { | 2934 | for (i = 0; i < ai->nports; ++i) { |
2933 | struct net_device *netdev; | 2935 | struct net_device *netdev; |
2934 | 2936 | ||
2935 | netdev = alloc_etherdev(sizeof(struct port_info)); | 2937 | netdev = alloc_etherdev_mq(sizeof(struct port_info), SGE_QSETS); |
2936 | if (!netdev) { | 2938 | if (!netdev) { |
2937 | err = -ENOMEM; | 2939 | err = -ENOMEM; |
2938 | goto out_free_dev; | 2940 | goto out_free_dev; |
@@ -2946,6 +2948,7 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
2946 | pi->rx_csum_offload = 1; | 2948 | pi->rx_csum_offload = 1; |
2947 | pi->port_id = i; | 2949 | pi->port_id = i; |
2948 | netif_carrier_off(netdev); | 2950 | netif_carrier_off(netdev); |
2951 | netif_tx_stop_all_queues(netdev); | ||
2949 | netdev->irq = pdev->irq; | 2952 | netdev->irq = pdev->irq; |
2950 | netdev->mem_start = mmio_start; | 2953 | netdev->mem_start = mmio_start; |
2951 | netdev->mem_end = mmio_start + mmio_len - 1; | 2954 | netdev->mem_end = mmio_start + mmio_len - 1; |
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index d3a6e245f1ef..63eb97473c8b 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c | |||
@@ -1120,10 +1120,10 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb, | |||
1120 | htonl(V_WR_TID(q->token))); | 1120 | htonl(V_WR_TID(q->token))); |
1121 | } | 1121 | } |
1122 | 1122 | ||
1123 | static inline void t3_stop_queue(struct net_device *dev, struct sge_qset *qs, | 1123 | static inline void t3_stop_tx_queue(struct netdev_queue *txq, |
1124 | struct sge_txq *q) | 1124 | struct sge_qset *qs, struct sge_txq *q) |
1125 | { | 1125 | { |
1126 | netif_stop_queue(dev); | 1126 | netif_tx_stop_queue(txq); |
1127 | set_bit(TXQ_ETH, &qs->txq_stopped); | 1127 | set_bit(TXQ_ETH, &qs->txq_stopped); |
1128 | q->stops++; | 1128 | q->stops++; |
1129 | } | 1129 | } |
@@ -1137,11 +1137,13 @@ static inline void t3_stop_queue(struct net_device *dev, struct sge_qset *qs, | |||
1137 | */ | 1137 | */ |
1138 | int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) | 1138 | int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) |
1139 | { | 1139 | { |
1140 | int qidx; | ||
1140 | unsigned int ndesc, pidx, credits, gen, compl; | 1141 | unsigned int ndesc, pidx, credits, gen, compl; |
1141 | const struct port_info *pi = netdev_priv(dev); | 1142 | const struct port_info *pi = netdev_priv(dev); |
1142 | struct adapter *adap = pi->adapter; | 1143 | struct adapter *adap = pi->adapter; |
1143 | struct sge_qset *qs = pi->qs; | 1144 | struct netdev_queue *txq; |
1144 | struct sge_txq *q = &qs->txq[TXQ_ETH]; | 1145 | struct sge_qset *qs; |
1146 | struct sge_txq *q; | ||
1145 | 1147 | ||
1146 | /* | 1148 | /* |
1147 | * The chip min packet length is 9 octets but play safe and reject | 1149 | * The chip min packet length is 9 octets but play safe and reject |
@@ -1152,6 +1154,11 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1152 | return NETDEV_TX_OK; | 1154 | return NETDEV_TX_OK; |
1153 | } | 1155 | } |
1154 | 1156 | ||
1157 | qidx = skb_get_queue_mapping(skb); | ||
1158 | qs = &pi->qs[qidx]; | ||
1159 | q = &qs->txq[TXQ_ETH]; | ||
1160 | txq = netdev_get_tx_queue(dev, qidx); | ||
1161 | |||
1155 | spin_lock(&q->lock); | 1162 | spin_lock(&q->lock); |
1156 | reclaim_completed_tx(adap, q); | 1163 | reclaim_completed_tx(adap, q); |
1157 | 1164 | ||
@@ -1159,7 +1166,7 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1159 | ndesc = calc_tx_descs(skb); | 1166 | ndesc = calc_tx_descs(skb); |
1160 | 1167 | ||
1161 | if (unlikely(credits < ndesc)) { | 1168 | if (unlikely(credits < ndesc)) { |
1162 | t3_stop_queue(dev, qs, q); | 1169 | t3_stop_tx_queue(txq, qs, q); |
1163 | dev_err(&adap->pdev->dev, | 1170 | dev_err(&adap->pdev->dev, |
1164 | "%s: Tx ring %u full while queue awake!\n", | 1171 | "%s: Tx ring %u full while queue awake!\n", |
1165 | dev->name, q->cntxt_id & 7); | 1172 | dev->name, q->cntxt_id & 7); |
@@ -1169,12 +1176,12 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1169 | 1176 | ||
1170 | q->in_use += ndesc; | 1177 | q->in_use += ndesc; |
1171 | if (unlikely(credits - ndesc < q->stop_thres)) { | 1178 | if (unlikely(credits - ndesc < q->stop_thres)) { |
1172 | t3_stop_queue(dev, qs, q); | 1179 | t3_stop_tx_queue(txq, qs, q); |
1173 | 1180 | ||
1174 | if (should_restart_tx(q) && | 1181 | if (should_restart_tx(q) && |
1175 | test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) { | 1182 | test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) { |
1176 | q->restarts++; | 1183 | q->restarts++; |
1177 | netif_wake_queue(dev); | 1184 | netif_tx_wake_queue(txq); |
1178 | } | 1185 | } |
1179 | } | 1186 | } |
1180 | 1187 | ||
@@ -1838,7 +1845,7 @@ static void restart_tx(struct sge_qset *qs) | |||
1838 | test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) { | 1845 | test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) { |
1839 | qs->txq[TXQ_ETH].restarts++; | 1846 | qs->txq[TXQ_ETH].restarts++; |
1840 | if (netif_running(qs->netdev)) | 1847 | if (netif_running(qs->netdev)) |
1841 | netif_wake_queue(qs->netdev); | 1848 | netif_tx_wake_queue(qs->tx_q); |
1842 | } | 1849 | } |
1843 | 1850 | ||
1844 | if (test_bit(TXQ_OFLD, &qs->txq_stopped) && | 1851 | if (test_bit(TXQ_OFLD, &qs->txq_stopped) && |
@@ -2824,6 +2831,7 @@ void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p) | |||
2824 | * @p: configuration parameters for this queue set | 2831 | * @p: configuration parameters for this queue set |
2825 | * @ntxq: number of Tx queues for the queue set | 2832 | * @ntxq: number of Tx queues for the queue set |
2826 | * @netdev: net device associated with this queue set | 2833 | * @netdev: net device associated with this queue set |
2834 | * @netdevq: net device TX queue associated with this queue set | ||
2827 | * | 2835 | * |
2828 | * Allocate resources and initialize an SGE queue set. A queue set | 2836 | * Allocate resources and initialize an SGE queue set. A queue set |
2829 | * comprises a response queue, two Rx free-buffer queues, and up to 3 | 2837 | * comprises a response queue, two Rx free-buffer queues, and up to 3 |
@@ -2832,7 +2840,8 @@ void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p) | |||
2832 | */ | 2840 | */ |
2833 | int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | 2841 | int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, |
2834 | int irq_vec_idx, const struct qset_params *p, | 2842 | int irq_vec_idx, const struct qset_params *p, |
2835 | int ntxq, struct net_device *dev) | 2843 | int ntxq, struct net_device *dev, |
2844 | struct netdev_queue *netdevq) | ||
2836 | { | 2845 | { |
2837 | int i, avail, ret = -ENOMEM; | 2846 | int i, avail, ret = -ENOMEM; |
2838 | struct sge_qset *q = &adapter->sge.qs[id]; | 2847 | struct sge_qset *q = &adapter->sge.qs[id]; |
@@ -2968,6 +2977,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | |||
2968 | 2977 | ||
2969 | q->adap = adapter; | 2978 | q->adap = adapter; |
2970 | q->netdev = dev; | 2979 | q->netdev = dev; |
2980 | q->tx_q = netdevq; | ||
2971 | t3_update_qset_coalesce(q, p); | 2981 | t3_update_qset_coalesce(q, p); |
2972 | 2982 | ||
2973 | init_lro_mgr(q, lro_mgr); | 2983 | init_lro_mgr(q, lro_mgr); |
diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h index bb8698a86754..b1b25c37aa10 100644 --- a/drivers/net/cxgb3/version.h +++ b/drivers/net/cxgb3/version.h | |||
@@ -35,7 +35,7 @@ | |||
35 | #define DRV_DESC "Chelsio T3 Network Driver" | 35 | #define DRV_DESC "Chelsio T3 Network Driver" |
36 | #define DRV_NAME "cxgb3" | 36 | #define DRV_NAME "cxgb3" |
37 | /* Driver version */ | 37 | /* Driver version */ |
38 | #define DRV_VERSION "1.1.0-ko" | 38 | #define DRV_VERSION "1.1.1-ko" |
39 | 39 | ||
40 | /* Firmware version */ | 40 | /* Firmware version */ |
41 | #define FW_VERSION_MAJOR 7 | 41 | #define FW_VERSION_MAJOR 7 |