Commit 89764d59 authored by David S. Miller's avatar David S. Miller

Merge branch 'fjes-next'

Taku Izumi says:

====================
FUJITSU Extended Socket driver version 1.1

This patchsets update FUJITSU Extended Socket network driver into version 1.1.
This mainly includes some improvements and minor bugfix.

v1->v2:
  - Remove ioctl and debugfs facility according to David comment
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f66bc941 8f180fad
...@@ -179,6 +179,8 @@ void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu) ...@@ -179,6 +179,8 @@ void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu)
for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++) for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++)
info->v1i.vlan_id[i] = vlan_id[i]; info->v1i.vlan_id[i] = vlan_id[i];
info->v1i.rx_status |= FJES_RX_MTU_CHANGING_DONE;
} }
void void
...@@ -214,6 +216,7 @@ static int fjes_hw_setup(struct fjes_hw *hw) ...@@ -214,6 +216,7 @@ static int fjes_hw_setup(struct fjes_hw *hw)
u8 mac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; u8 mac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
struct fjes_device_command_param param; struct fjes_device_command_param param;
struct ep_share_mem_info *buf_pair; struct ep_share_mem_info *buf_pair;
unsigned long flags;
size_t mem_size; size_t mem_size;
int result; int result;
int epidx; int epidx;
...@@ -262,10 +265,12 @@ static int fjes_hw_setup(struct fjes_hw *hw) ...@@ -262,10 +265,12 @@ static int fjes_hw_setup(struct fjes_hw *hw)
if (result) if (result)
return result; return result;
spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf(&buf_pair->tx, mac, fjes_hw_setup_epbuf(&buf_pair->tx, mac,
fjes_support_mtu[0]); fjes_support_mtu[0]);
fjes_hw_setup_epbuf(&buf_pair->rx, mac, fjes_hw_setup_epbuf(&buf_pair->rx, mac,
fjes_support_mtu[0]); fjes_support_mtu[0]);
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
} }
} }
...@@ -327,6 +332,7 @@ int fjes_hw_init(struct fjes_hw *hw) ...@@ -327,6 +332,7 @@ int fjes_hw_init(struct fjes_hw *hw)
INIT_WORK(&hw->epstop_task, fjes_hw_epstop_task); INIT_WORK(&hw->epstop_task, fjes_hw_epstop_task);
mutex_init(&hw->hw_info.lock); mutex_init(&hw->hw_info.lock);
spin_lock_init(&hw->rx_status_lock);
hw->max_epid = fjes_hw_get_max_epid(hw); hw->max_epid = fjes_hw_get_max_epid(hw);
hw->my_epid = fjes_hw_get_my_epid(hw); hw->my_epid = fjes_hw_get_my_epid(hw);
...@@ -734,6 +740,7 @@ fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid) ...@@ -734,6 +740,7 @@ fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid)
void fjes_hw_raise_epstop(struct fjes_hw *hw) void fjes_hw_raise_epstop(struct fjes_hw *hw)
{ {
enum ep_partner_status status; enum ep_partner_status status;
unsigned long flags;
int epidx; int epidx;
for (epidx = 0; epidx < hw->max_epid; epidx++) { for (epidx = 0; epidx < hw->max_epid; epidx++) {
...@@ -753,8 +760,10 @@ void fjes_hw_raise_epstop(struct fjes_hw *hw) ...@@ -753,8 +760,10 @@ void fjes_hw_raise_epstop(struct fjes_hw *hw)
set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
set_bit(epidx, &hw->txrx_stop_req_bit); set_bit(epidx, &hw->txrx_stop_req_bit);
spin_lock_irqsave(&hw->rx_status_lock, flags);
hw->ep_shm_info[epidx].tx.info->v1i.rx_status |= hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
FJES_RX_STOP_REQ_REQUEST; FJES_RX_STOP_REQ_REQUEST;
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
} }
} }
...@@ -810,7 +819,8 @@ bool fjes_hw_check_mtu(struct epbuf_handler *epbh, u32 mtu) ...@@ -810,7 +819,8 @@ bool fjes_hw_check_mtu(struct epbuf_handler *epbh, u32 mtu)
{ {
union ep_buffer_info *info = epbh->info; union ep_buffer_info *info = epbh->info;
return (info->v1i.frame_max == FJES_MTU_TO_FRAME_SIZE(mtu)); return ((info->v1i.frame_max == FJES_MTU_TO_FRAME_SIZE(mtu)) &&
info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE);
} }
bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id) bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
...@@ -863,6 +873,9 @@ bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh) ...@@ -863,6 +873,9 @@ bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
{ {
union ep_buffer_info *info = epbh->info; union ep_buffer_info *info = epbh->info;
if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE))
return true;
if (info->v1i.count_max == 0) if (info->v1i.count_max == 0)
return true; return true;
...@@ -932,6 +945,7 @@ static void fjes_hw_update_zone_task(struct work_struct *work) ...@@ -932,6 +945,7 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
struct fjes_adapter *adapter; struct fjes_adapter *adapter;
struct net_device *netdev; struct net_device *netdev;
unsigned long flags;
ulong unshare_bit = 0; ulong unshare_bit = 0;
ulong share_bit = 0; ulong share_bit = 0;
...@@ -1024,8 +1038,10 @@ static void fjes_hw_update_zone_task(struct work_struct *work) ...@@ -1024,8 +1038,10 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
continue; continue;
if (test_bit(epidx, &share_bit)) { if (test_bit(epidx, &share_bit)) {
spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx, fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
netdev->dev_addr, netdev->mtu); netdev->dev_addr, netdev->mtu);
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
mutex_lock(&hw->hw_info.lock); mutex_lock(&hw->hw_info.lock);
...@@ -1069,10 +1085,14 @@ static void fjes_hw_update_zone_task(struct work_struct *work) ...@@ -1069,10 +1085,14 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
mutex_unlock(&hw->hw_info.lock); mutex_unlock(&hw->hw_info.lock);
if (ret == 0) if (ret == 0) {
spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf( fjes_hw_setup_epbuf(
&hw->ep_shm_info[epidx].tx, &hw->ep_shm_info[epidx].tx,
netdev->dev_addr, netdev->mtu); netdev->dev_addr, netdev->mtu);
spin_unlock_irqrestore(&hw->rx_status_lock,
flags);
}
} }
if (test_bit(epidx, &irq_bit)) { if (test_bit(epidx, &irq_bit)) {
...@@ -1080,9 +1100,11 @@ static void fjes_hw_update_zone_task(struct work_struct *work) ...@@ -1080,9 +1100,11 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
REG_ICTL_MASK_TXRX_STOP_REQ); REG_ICTL_MASK_TXRX_STOP_REQ);
set_bit(epidx, &hw->txrx_stop_req_bit); set_bit(epidx, &hw->txrx_stop_req_bit);
spin_lock_irqsave(&hw->rx_status_lock, flags);
hw->ep_shm_info[epidx].tx. hw->ep_shm_info[epidx].tx.
info->v1i.rx_status |= info->v1i.rx_status |=
FJES_RX_STOP_REQ_REQUEST; FJES_RX_STOP_REQ_REQUEST;
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
} }
} }
...@@ -1098,6 +1120,7 @@ static void fjes_hw_epstop_task(struct work_struct *work) ...@@ -1098,6 +1120,7 @@ static void fjes_hw_epstop_task(struct work_struct *work)
{ {
struct fjes_hw *hw = container_of(work, struct fjes_hw, epstop_task); struct fjes_hw *hw = container_of(work, struct fjes_hw, epstop_task);
struct fjes_adapter *adapter = (struct fjes_adapter *)hw->back; struct fjes_adapter *adapter = (struct fjes_adapter *)hw->back;
unsigned long flags;
ulong remain_bit; ulong remain_bit;
int epid_bit; int epid_bit;
...@@ -1105,9 +1128,12 @@ static void fjes_hw_epstop_task(struct work_struct *work) ...@@ -1105,9 +1128,12 @@ static void fjes_hw_epstop_task(struct work_struct *work)
while ((remain_bit = hw->epstop_req_bit)) { while ((remain_bit = hw->epstop_req_bit)) {
for (epid_bit = 0; remain_bit; remain_bit >>= 1, epid_bit++) { for (epid_bit = 0; remain_bit; remain_bit >>= 1, epid_bit++) {
if (remain_bit & 1) { if (remain_bit & 1) {
spin_lock_irqsave(&hw->rx_status_lock, flags);
hw->ep_shm_info[epid_bit]. hw->ep_shm_info[epid_bit].
tx.info->v1i.rx_status |= tx.info->v1i.rx_status |=
FJES_RX_STOP_REQ_DONE; FJES_RX_STOP_REQ_DONE;
spin_unlock_irqrestore(&hw->rx_status_lock,
flags);
clear_bit(epid_bit, &hw->epstop_req_bit); clear_bit(epid_bit, &hw->epstop_req_bit);
set_bit(epid_bit, set_bit(epid_bit,
......
...@@ -33,9 +33,9 @@ struct fjes_hw; ...@@ -33,9 +33,9 @@ struct fjes_hw;
#define EP_BUFFER_SUPPORT_VLAN_MAX 4 #define EP_BUFFER_SUPPORT_VLAN_MAX 4
#define EP_BUFFER_INFO_SIZE 4096 #define EP_BUFFER_INFO_SIZE 4096
#define FJES_DEVICE_RESET_TIMEOUT ((17 + 1) * 3) /* sec */ #define FJES_DEVICE_RESET_TIMEOUT ((17 + 1) * 3 * 8) /* sec */
#define FJES_COMMAND_REQ_TIMEOUT (5 + 1) /* sec */ #define FJES_COMMAND_REQ_TIMEOUT ((5 + 1) * 3 * 8) /* sec */
#define FJES_COMMAND_REQ_BUFF_TIMEOUT (8 * 3) /* sec */ #define FJES_COMMAND_REQ_BUFF_TIMEOUT (60 * 3) /* sec */
#define FJES_COMMAND_EPSTOP_WAIT_TIMEOUT (1) /* sec */ #define FJES_COMMAND_EPSTOP_WAIT_TIMEOUT (1) /* sec */
#define FJES_CMD_REQ_ERR_INFO_PARAM (0x0001) #define FJES_CMD_REQ_ERR_INFO_PARAM (0x0001)
...@@ -57,6 +57,7 @@ struct fjes_hw; ...@@ -57,6 +57,7 @@ struct fjes_hw;
#define FJES_RX_STOP_REQ_DONE (0x1) #define FJES_RX_STOP_REQ_DONE (0x1)
#define FJES_RX_STOP_REQ_REQUEST (0x2) #define FJES_RX_STOP_REQ_REQUEST (0x2)
#define FJES_RX_POLL_WORK (0x4) #define FJES_RX_POLL_WORK (0x4)
#define FJES_RX_MTU_CHANGING_DONE (0x8)
#define EP_BUFFER_SIZE \ #define EP_BUFFER_SIZE \
(((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \ (((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \
...@@ -299,6 +300,8 @@ struct fjes_hw { ...@@ -299,6 +300,8 @@ struct fjes_hw {
u8 *base; u8 *base;
struct fjes_hw_info hw_info; struct fjes_hw_info hw_info;
spinlock_t rx_status_lock; /* spinlock for rx_status */
}; };
int fjes_hw_init(struct fjes_hw *); int fjes_hw_init(struct fjes_hw *);
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include "fjes.h" #include "fjes.h"
#define MAJ 1 #define MAJ 1
#define MIN 0 #define MIN 1
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
#define DRV_NAME "fjes" #define DRV_NAME "fjes"
char fjes_driver_name[] = DRV_NAME; char fjes_driver_name[] = DRV_NAME;
...@@ -290,6 +290,7 @@ static int fjes_close(struct net_device *netdev) ...@@ -290,6 +290,7 @@ static int fjes_close(struct net_device *netdev)
{ {
struct fjes_adapter *adapter = netdev_priv(netdev); struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = &adapter->hw; struct fjes_hw *hw = &adapter->hw;
unsigned long flags;
int epidx; int epidx;
netif_tx_stop_all_queues(netdev); netif_tx_stop_all_queues(netdev);
...@@ -299,13 +300,18 @@ static int fjes_close(struct net_device *netdev) ...@@ -299,13 +300,18 @@ static int fjes_close(struct net_device *netdev)
napi_disable(&adapter->napi); napi_disable(&adapter->napi);
spin_lock_irqsave(&hw->rx_status_lock, flags);
for (epidx = 0; epidx < hw->max_epid; epidx++) { for (epidx = 0; epidx < hw->max_epid; epidx++) {
if (epidx == hw->my_epid) if (epidx == hw->my_epid)
continue; continue;
adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status &= if (fjes_hw_get_partner_ep_status(hw, epidx) ==
~FJES_RX_POLL_WORK; EP_PARTNER_SHARED)
adapter->hw.ep_shm_info[epidx]
.tx.info->v1i.rx_status &=
~FJES_RX_POLL_WORK;
} }
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
fjes_free_irq(adapter); fjes_free_irq(adapter);
...@@ -330,6 +336,7 @@ static int fjes_setup_resources(struct fjes_adapter *adapter) ...@@ -330,6 +336,7 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
struct ep_share_mem_info *buf_pair; struct ep_share_mem_info *buf_pair;
struct fjes_hw *hw = &adapter->hw; struct fjes_hw *hw = &adapter->hw;
unsigned long flags;
int result; int result;
int epidx; int epidx;
...@@ -371,8 +378,10 @@ static int fjes_setup_resources(struct fjes_adapter *adapter) ...@@ -371,8 +378,10 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
buf_pair = &hw->ep_shm_info[epidx]; buf_pair = &hw->ep_shm_info[epidx];
spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr, fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr,
netdev->mtu); netdev->mtu);
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
if (fjes_hw_epid_is_same_zone(hw, epidx)) { if (fjes_hw_epid_is_same_zone(hw, epidx)) {
mutex_lock(&hw->hw_info.lock); mutex_lock(&hw->hw_info.lock);
...@@ -402,6 +411,7 @@ static void fjes_free_resources(struct fjes_adapter *adapter) ...@@ -402,6 +411,7 @@ static void fjes_free_resources(struct fjes_adapter *adapter)
struct ep_share_mem_info *buf_pair; struct ep_share_mem_info *buf_pair;
struct fjes_hw *hw = &adapter->hw; struct fjes_hw *hw = &adapter->hw;
bool reset_flag = false; bool reset_flag = false;
unsigned long flags;
int result; int result;
int epidx; int epidx;
...@@ -418,8 +428,10 @@ static void fjes_free_resources(struct fjes_adapter *adapter) ...@@ -418,8 +428,10 @@ static void fjes_free_resources(struct fjes_adapter *adapter)
buf_pair = &hw->ep_shm_info[epidx]; buf_pair = &hw->ep_shm_info[epidx];
spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf(&buf_pair->tx, fjes_hw_setup_epbuf(&buf_pair->tx,
netdev->dev_addr, netdev->mtu); netdev->dev_addr, netdev->mtu);
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
clear_bit(epidx, &hw->txrx_stop_req_bit); clear_bit(epidx, &hw->txrx_stop_req_bit);
} }
...@@ -481,6 +493,9 @@ static void fjes_tx_stall_task(struct work_struct *work) ...@@ -481,6 +493,9 @@ static void fjes_tx_stall_task(struct work_struct *work)
info = adapter->hw.ep_shm_info[epid].tx.info; info = adapter->hw.ep_shm_info[epid].tx.info;
if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE))
return;
if (EP_RING_FULL(info->v1i.head, info->v1i.tail, if (EP_RING_FULL(info->v1i.head, info->v1i.tail,
info->v1i.count_max)) { info->v1i.count_max)) {
all_queue_available = 0; all_queue_available = 0;
...@@ -549,7 +564,8 @@ static void fjes_raise_intr_rxdata_task(struct work_struct *work) ...@@ -549,7 +564,8 @@ static void fjes_raise_intr_rxdata_task(struct work_struct *work)
if ((hw->ep_shm_info[epid].tx_status_work == if ((hw->ep_shm_info[epid].tx_status_work ==
FJES_TX_DELAY_SEND_PENDING) && FJES_TX_DELAY_SEND_PENDING) &&
(pstatus == EP_PARTNER_SHARED) && (pstatus == EP_PARTNER_SHARED) &&
!(hw->ep_shm_info[epid].rx.info->v1i.rx_status)) { !(hw->ep_shm_info[epid].rx.info->v1i.rx_status &
FJES_RX_POLL_WORK)) {
fjes_hw_raise_interrupt(hw, epid, fjes_hw_raise_interrupt(hw, epid,
REG_ICTL_MASK_RX_DATA); REG_ICTL_MASK_RX_DATA);
} }
...@@ -653,7 +669,7 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -653,7 +669,7 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
&adapter->hw.ep_shm_info[dest_epid].rx, 0)) { &adapter->hw.ep_shm_info[dest_epid].rx, 0)) {
/* version is NOT 0 */ /* version is NOT 0 */
adapter->stats64.tx_carrier_errors += 1; adapter->stats64.tx_carrier_errors += 1;
hw->ep_shm_info[my_epid].net_stats hw->ep_shm_info[dest_epid].net_stats
.tx_carrier_errors += 1; .tx_carrier_errors += 1;
ret = NETDEV_TX_OK; ret = NETDEV_TX_OK;
...@@ -661,9 +677,9 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -661,9 +677,9 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
&adapter->hw.ep_shm_info[dest_epid].rx, &adapter->hw.ep_shm_info[dest_epid].rx,
netdev->mtu)) { netdev->mtu)) {
adapter->stats64.tx_dropped += 1; adapter->stats64.tx_dropped += 1;
hw->ep_shm_info[my_epid].net_stats.tx_dropped += 1; hw->ep_shm_info[dest_epid].net_stats.tx_dropped += 1;
adapter->stats64.tx_errors += 1; adapter->stats64.tx_errors += 1;
hw->ep_shm_info[my_epid].net_stats.tx_errors += 1; hw->ep_shm_info[dest_epid].net_stats.tx_errors += 1;
ret = NETDEV_TX_OK; ret = NETDEV_TX_OK;
} else if (vlan && } else if (vlan &&
...@@ -694,10 +710,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -694,10 +710,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
(long)adapter->tx_start_jiffies) >= (long)adapter->tx_start_jiffies) >=
FJES_TX_RETRY_TIMEOUT) { FJES_TX_RETRY_TIMEOUT) {
adapter->stats64.tx_fifo_errors += 1; adapter->stats64.tx_fifo_errors += 1;
hw->ep_shm_info[my_epid].net_stats hw->ep_shm_info[dest_epid].net_stats
.tx_fifo_errors += 1; .tx_fifo_errors += 1;
adapter->stats64.tx_errors += 1; adapter->stats64.tx_errors += 1;
hw->ep_shm_info[my_epid].net_stats hw->ep_shm_info[dest_epid].net_stats
.tx_errors += 1; .tx_errors += 1;
ret = NETDEV_TX_OK; ret = NETDEV_TX_OK;
...@@ -714,10 +730,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -714,10 +730,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
} else { } else {
if (!is_multi) { if (!is_multi) {
adapter->stats64.tx_packets += 1; adapter->stats64.tx_packets += 1;
hw->ep_shm_info[my_epid].net_stats hw->ep_shm_info[dest_epid].net_stats
.tx_packets += 1; .tx_packets += 1;
adapter->stats64.tx_bytes += len; adapter->stats64.tx_bytes += len;
hw->ep_shm_info[my_epid].net_stats hw->ep_shm_info[dest_epid].net_stats
.tx_bytes += len; .tx_bytes += len;
} }
...@@ -759,9 +775,12 @@ fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) ...@@ -759,9 +775,12 @@ fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
static int fjes_change_mtu(struct net_device *netdev, int new_mtu) static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
{ {
struct fjes_adapter *adapter = netdev_priv(netdev);
bool running = netif_running(netdev); bool running = netif_running(netdev);
int ret = 0; struct fjes_hw *hw = &adapter->hw;
int idx; unsigned long flags;
int ret = -EINVAL;
int idx, epidx;
for (idx = 0; fjes_support_mtu[idx] != 0; idx++) { for (idx = 0; fjes_support_mtu[idx] != 0; idx++) {
if (new_mtu <= fjes_support_mtu[idx]) { if (new_mtu <= fjes_support_mtu[idx]) {
...@@ -769,19 +788,59 @@ static int fjes_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -769,19 +788,59 @@ static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
if (new_mtu == netdev->mtu) if (new_mtu == netdev->mtu)
return 0; return 0;
if (running) ret = 0;
fjes_close(netdev); break;
}
}
if (ret)
return ret;
if (running) {
spin_lock_irqsave(&hw->rx_status_lock, flags);
for (epidx = 0; epidx < hw->max_epid; epidx++) {
if (epidx == hw->my_epid)
continue;
hw->ep_shm_info[epidx].tx.info->v1i.rx_status &=
~FJES_RX_MTU_CHANGING_DONE;
}
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
netif_tx_stop_all_queues(netdev);
netif_carrier_off(netdev);
cancel_work_sync(&adapter->tx_stall_task);
napi_disable(&adapter->napi);
msleep(1000);
netif_tx_stop_all_queues(netdev);
}
netdev->mtu = new_mtu;
netdev->mtu = new_mtu; if (running) {
spin_lock_irqsave(&hw->rx_status_lock, flags);
for (epidx = 0; epidx < hw->max_epid; epidx++) {
if (epidx == hw->my_epid)
continue;
if (running) spin_lock_irqsave(&hw->rx_status_lock, flags);
ret = fjes_open(netdev); fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
netdev->dev_addr,
netdev->mtu);
return ret; hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
FJES_RX_MTU_CHANGING_DONE;
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
} }
netif_tx_wake_all_queues(netdev);
netif_carrier_on(netdev);
napi_enable(&adapter->napi);
napi_schedule(&adapter->napi);
} }
return -EINVAL; return ret;
} }
static int fjes_vlan_rx_add_vid(struct net_device *netdev, static int fjes_vlan_rx_add_vid(struct net_device *netdev,
...@@ -825,6 +884,7 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter, ...@@ -825,6 +884,7 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
{ {
struct fjes_hw *hw = &adapter->hw; struct fjes_hw *hw = &adapter->hw;
enum ep_partner_status status; enum ep_partner_status status;
unsigned long flags;
status = fjes_hw_get_partner_ep_status(hw, src_epid); status = fjes_hw_get_partner_ep_status(hw, src_epid);
switch (status) { switch (status) {
...@@ -834,8 +894,10 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter, ...@@ -834,8 +894,10 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
break; break;
case EP_PARTNER_WAITING: case EP_PARTNER_WAITING:
if (src_epid < hw->my_epid) { if (src_epid < hw->my_epid) {
spin_lock_irqsave(&hw->rx_status_lock, flags);
hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |= hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |=
FJES_RX_STOP_REQ_DONE; FJES_RX_STOP_REQ_DONE;
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
clear_bit(src_epid, &hw->txrx_stop_req_bit); clear_bit(src_epid, &hw->txrx_stop_req_bit);
set_bit(src_epid, &adapter->unshare_watch_bitmask); set_bit(src_epid, &adapter->unshare_watch_bitmask);
...@@ -861,14 +923,17 @@ static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid) ...@@ -861,14 +923,17 @@ static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
{ {
struct fjes_hw *hw = &adapter->hw; struct fjes_hw *hw = &adapter->hw;
enum ep_partner_status status; enum ep_partner_status status;
unsigned long flags;
set_bit(src_epid, &hw->hw_info.buffer_unshare_reserve_bit); set_bit(src_epid, &hw->hw_info.buffer_unshare_reserve_bit);
status = fjes_hw_get_partner_ep_status(hw, src_epid); status = fjes_hw_get_partner_ep_status(hw, src_epid);
switch (status) { switch (status) {
case EP_PARTNER_WAITING: case EP_PARTNER_WAITING:
spin_lock_irqsave(&hw->rx_status_lock, flags);
hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |= hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |=
FJES_RX_STOP_REQ_DONE; FJES_RX_STOP_REQ_DONE;
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
clear_bit(src_epid, &hw->txrx_stop_req_bit); clear_bit(src_epid, &hw->txrx_stop_req_bit);
/* fall through */ /* fall through */
case EP_PARTNER_UNSHARE: case EP_PARTNER_UNSHARE:
...@@ -1001,13 +1066,17 @@ static int fjes_poll(struct napi_struct *napi, int budget) ...@@ -1001,13 +1066,17 @@ static int fjes_poll(struct napi_struct *napi, int budget)
size_t frame_len; size_t frame_len;
void *frame; void *frame;
spin_lock(&hw->rx_status_lock);
for (epidx = 0; epidx < hw->max_epid; epidx++) { for (epidx = 0; epidx < hw->max_epid; epidx++) {
if (epidx == hw->my_epid) if (epidx == hw->my_epid)
continue; continue;
adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status |= if (fjes_hw_get_partner_ep_status(hw, epidx) ==
FJES_RX_POLL_WORK; EP_PARTNER_SHARED)
adapter->hw.ep_shm_info[epidx]
.tx.info->v1i.rx_status |= FJES_RX_POLL_WORK;
} }
spin_unlock(&hw->rx_status_lock);
while (work_done < budget) { while (work_done < budget) {
prefetch(&adapter->hw); prefetch(&adapter->hw);
...@@ -1065,13 +1134,17 @@ static int fjes_poll(struct napi_struct *napi, int budget) ...@@ -1065,13 +1134,17 @@ static int fjes_poll(struct napi_struct *napi, int budget)
if (((long)jiffies - (long)adapter->rx_last_jiffies) < 3) { if (((long)jiffies - (long)adapter->rx_last_jiffies) < 3) {
napi_reschedule(napi); napi_reschedule(napi);
} else { } else {
spin_lock(&hw->rx_status_lock);
for (epidx = 0; epidx < hw->max_epid; epidx++) { for (epidx = 0; epidx < hw->max_epid; epidx++) {
if (epidx == hw->my_epid) if (epidx == hw->my_epid)
continue; continue;
adapter->hw.ep_shm_info[epidx] if (fjes_hw_get_partner_ep_status(hw, epidx) ==
.tx.info->v1i.rx_status &= EP_PARTNER_SHARED)
adapter->hw.ep_shm_info[epidx].tx
.info->v1i.rx_status &=
~FJES_RX_POLL_WORK; ~FJES_RX_POLL_WORK;
} }
spin_unlock(&hw->rx_status_lock);
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, false); fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, false);
} }
...@@ -1203,7 +1276,7 @@ static void fjes_netdev_setup(struct net_device *netdev) ...@@ -1203,7 +1276,7 @@ static void fjes_netdev_setup(struct net_device *netdev)
netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL; netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL;
netdev->netdev_ops = &fjes_netdev_ops; netdev->netdev_ops = &fjes_netdev_ops;
fjes_set_ethtool_ops(netdev); fjes_set_ethtool_ops(netdev);
netdev->mtu = fjes_support_mtu[0]; netdev->mtu = fjes_support_mtu[3];
netdev->flags |= IFF_BROADCAST; netdev->flags |= IFF_BROADCAST;
netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER; netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
} }
...@@ -1240,6 +1313,7 @@ static void fjes_watch_unshare_task(struct work_struct *work) ...@@ -1240,6 +1313,7 @@ static void fjes_watch_unshare_task(struct work_struct *work)
int max_epid, my_epid, epidx; int max_epid, my_epid, epidx;
int stop_req, stop_req_done; int stop_req, stop_req_done;
ulong unshare_watch_bitmask; ulong unshare_watch_bitmask;
unsigned long flags;
int wait_time = 0; int wait_time = 0;
int is_shared; int is_shared;
int ret; int ret;
...@@ -1292,8 +1366,10 @@ static void fjes_watch_unshare_task(struct work_struct *work) ...@@ -1292,8 +1366,10 @@ static void fjes_watch_unshare_task(struct work_struct *work)
} }
mutex_unlock(&hw->hw_info.lock); mutex_unlock(&hw->hw_info.lock);
spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx, fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
netdev->dev_addr, netdev->mtu); netdev->dev_addr, netdev->mtu);
spin_unlock_irqrestore(&hw->rx_status_lock, flags);
clear_bit(epidx, &hw->txrx_stop_req_bit); clear_bit(epidx, &hw->txrx_stop_req_bit);
clear_bit(epidx, &unshare_watch_bitmask); clear_bit(epidx, &unshare_watch_bitmask);
...@@ -1331,9 +1407,12 @@ static void fjes_watch_unshare_task(struct work_struct *work) ...@@ -1331,9 +1407,12 @@ static void fjes_watch_unshare_task(struct work_struct *work)
} }
mutex_unlock(&hw->hw_info.lock); mutex_unlock(&hw->hw_info.lock);
spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf( fjes_hw_setup_epbuf(
&hw->ep_shm_info[epidx].tx, &hw->ep_shm_info[epidx].tx,
netdev->dev_addr, netdev->mtu); netdev->dev_addr, netdev->mtu);
spin_unlock_irqrestore(&hw->rx_status_lock,
flags);
clear_bit(epidx, &hw->txrx_stop_req_bit); clear_bit(epidx, &hw->txrx_stop_req_bit);
clear_bit(epidx, &unshare_watch_bitmask); clear_bit(epidx, &unshare_watch_bitmask);
...@@ -1341,8 +1420,11 @@ static void fjes_watch_unshare_task(struct work_struct *work) ...@@ -1341,8 +1420,11 @@ static void fjes_watch_unshare_task(struct work_struct *work)
} }
if (test_bit(epidx, &unshare_watch_bitmask)) { if (test_bit(epidx, &unshare_watch_bitmask)) {
spin_lock_irqsave(&hw->rx_status_lock, flags);
hw->ep_shm_info[epidx].tx.info->v1i.rx_status &= hw->ep_shm_info[epidx].tx.info->v1i.rx_status &=
~FJES_RX_STOP_REQ_DONE; ~FJES_RX_STOP_REQ_DONE;
spin_unlock_irqrestore(&hw->rx_status_lock,
flags);
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment