aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c57
1 files changed, 37 insertions, 20 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 8a87e16e732f..c5de65c6f6e1 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1049,6 +1049,40 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
1049 return le; 1049 return le;
1050} 1050}
1051 1051
1052static unsigned sky2_get_rx_threshold(struct sky2_port* sky2)
1053{
1054 unsigned size;
1055
1056 /* Space needed for frame data + headers rounded up */
1057 size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
1058
1059 /* Stopping point for hardware truncation */
1060 return (size - 8) / sizeof(u32);
1061}
1062
1063static unsigned sky2_get_rx_data_size(struct sky2_port* sky2)
1064{
1065 struct rx_ring_info *re;
1066 unsigned size;
1067
1068 /* Space needed for frame data + headers rounded up */
1069 size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
1070
1071 sky2->rx_nfrags = size >> PAGE_SHIFT;
1072 BUG_ON(sky2->rx_nfrags > ARRAY_SIZE(re->frag_addr));
1073
1074 /* Compute residue after pages */
1075 size -= sky2->rx_nfrags << PAGE_SHIFT;
1076
1077 /* Optimize to handle small packets and headers */
1078 if (size < copybreak)
1079 size = copybreak;
1080 if (size < ETH_HLEN)
1081 size = ETH_HLEN;
1082
1083 return size;
1084}
1085
1052/* Build description to hardware for one receive segment */ 1086/* Build description to hardware for one receive segment */
1053static void sky2_rx_add(struct sky2_port *sky2, u8 op, 1087static void sky2_rx_add(struct sky2_port *sky2, u8 op,
1054 dma_addr_t map, unsigned len) 1088 dma_addr_t map, unsigned len)
@@ -1343,7 +1377,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
1343 struct sky2_hw *hw = sky2->hw; 1377 struct sky2_hw *hw = sky2->hw;
1344 struct rx_ring_info *re; 1378 struct rx_ring_info *re;
1345 unsigned rxq = rxqaddr[sky2->port]; 1379 unsigned rxq = rxqaddr[sky2->port];
1346 unsigned i, size, thresh; 1380 unsigned i, thresh;
1347 1381
1348 sky2->rx_put = sky2->rx_next = 0; 1382 sky2->rx_put = sky2->rx_next = 0;
1349 sky2_qset(hw, rxq); 1383 sky2_qset(hw, rxq);
@@ -1364,25 +1398,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
1364 if (!(hw->flags & SKY2_HW_NEW_LE)) 1398 if (!(hw->flags & SKY2_HW_NEW_LE))
1365 rx_set_checksum(sky2); 1399 rx_set_checksum(sky2);
1366 1400
1367 /* Space needed for frame data + headers rounded up */ 1401 sky2->rx_data_size = sky2_get_rx_data_size(sky2);
1368 size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
1369
1370 /* Stopping point for hardware truncation */
1371 thresh = (size - 8) / sizeof(u32);
1372
1373 sky2->rx_nfrags = size >> PAGE_SHIFT;
1374 BUG_ON(sky2->rx_nfrags > ARRAY_SIZE(re->frag_addr));
1375
1376 /* Compute residue after pages */
1377 size -= sky2->rx_nfrags << PAGE_SHIFT;
1378
1379 /* Optimize to handle small packets and headers */
1380 if (size < copybreak)
1381 size = copybreak;
1382 if (size < ETH_HLEN)
1383 size = ETH_HLEN;
1384
1385 sky2->rx_data_size = size;
1386 1402
1387 /* Fill Rx ring */ 1403 /* Fill Rx ring */
1388 for (i = 0; i < sky2->rx_pending; i++) { 1404 for (i = 0; i < sky2->rx_pending; i++) {
@@ -1407,6 +1423,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
1407 * the register is limited to 9 bits, so if you do frames > 2052 1423 * the register is limited to 9 bits, so if you do frames > 2052
1408 * you better get the MTU right! 1424 * you better get the MTU right!
1409 */ 1425 */
1426 thresh = sky2_get_rx_threshold(sky2);
1410 if (thresh > 0x1ff) 1427 if (thresh > 0x1ff)
1411 sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF); 1428 sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF);
1412 else { 1429 else {