add locking
Reviewed by: Prafulla Deuskar <pdeuskar@FreeBSD.ORG> Sponsored by: FreeBSD Foundation
This commit is contained in:
parent
ee3ce1c29c
commit
266f0707bb
@ -123,6 +123,7 @@ static void em_start(struct ifnet *);
|
||||
static int em_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void em_watchdog(struct ifnet *);
|
||||
static void em_init(void *);
|
||||
static void em_init_locked(struct adapter *);
|
||||
static void em_stop(void *);
|
||||
static void em_media_status(struct ifnet *, struct ifmediareq *);
|
||||
static int em_media_change(struct ifnet *);
|
||||
@ -286,23 +287,22 @@ static int
|
||||
em_attach(device_t dev)
|
||||
{
|
||||
struct adapter * adapter;
|
||||
int s;
|
||||
int tsize, rsize;
|
||||
int error = 0;
|
||||
|
||||
INIT_DEBUGOUT("em_attach: begin");
|
||||
s = splimp();
|
||||
|
||||
/* Allocate, clear, and link in our adapter structure */
|
||||
if (!(adapter = device_get_softc(dev))) {
|
||||
printf("em: adapter structure allocation failed\n");
|
||||
splx(s);
|
||||
return(ENOMEM);
|
||||
}
|
||||
bzero(adapter, sizeof(struct adapter ));
|
||||
adapter->dev = dev;
|
||||
adapter->osdep.dev = dev;
|
||||
adapter->unit = device_get_unit(dev);
|
||||
mtx_init(&adapter->mtx, device_get_nameunit(dev),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
|
||||
if (em_adapter_list != NULL)
|
||||
em_adapter_list->prev = adapter;
|
||||
@ -334,8 +334,8 @@ em_attach(device_t dev)
|
||||
(void *)adapter, 0,
|
||||
em_sysctl_stats, "I", "Statistics");
|
||||
|
||||
callout_handle_init(&adapter->timer_handle);
|
||||
callout_handle_init(&adapter->tx_fifo_timer_handle);
|
||||
callout_init(&adapter->timer, CALLOUT_MPSAFE);
|
||||
callout_init(&adapter->tx_fifo_timer, CALLOUT_MPSAFE);
|
||||
|
||||
/* Determine hardware revision */
|
||||
em_identify_hardware(adapter);
|
||||
@ -494,7 +494,6 @@ em_attach(device_t dev)
|
||||
adapter->pcix_82544 = FALSE;
|
||||
}
|
||||
INIT_DEBUGOUT("em_attach: end");
|
||||
splx(s);
|
||||
return(0);
|
||||
|
||||
err_mac_addr:
|
||||
@ -507,7 +506,6 @@ em_attach(device_t dev)
|
||||
em_free_pci_resources(adapter);
|
||||
sysctl_ctx_free(&adapter->sysctl_ctx);
|
||||
err_sysctl:
|
||||
splx(s);
|
||||
return(error);
|
||||
|
||||
}
|
||||
@ -527,13 +525,13 @@ em_detach(device_t dev)
|
||||
{
|
||||
struct adapter * adapter = device_get_softc(dev);
|
||||
struct ifnet *ifp = &adapter->interface_data.ac_if;
|
||||
int s;
|
||||
|
||||
INIT_DEBUGOUT("em_detach: begin");
|
||||
s = splimp();
|
||||
|
||||
EM_LOCK(adapter);
|
||||
em_stop(adapter);
|
||||
em_phy_hw_reset(&adapter->hw);
|
||||
EM_UNLOCK(adapter);
|
||||
#if __FreeBSD_version < 500000
|
||||
ether_ifdetach(&adapter->interface_data.ac_if, ETHER_BPF_SUPPORTED);
|
||||
#else
|
||||
@ -567,7 +565,6 @@ em_detach(device_t dev)
|
||||
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
|
||||
ifp->if_timer = 0;
|
||||
|
||||
splx(s);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -581,7 +578,9 @@ static int
|
||||
em_shutdown(device_t dev)
|
||||
{
|
||||
struct adapter *adapter = device_get_softc(dev);
|
||||
EM_LOCK(adapter);
|
||||
em_stop(adapter);
|
||||
EM_UNLOCK(adapter);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -597,16 +596,16 @@ em_shutdown(device_t dev)
|
||||
**********************************************************************/
|
||||
|
||||
static void
|
||||
em_start(struct ifnet *ifp)
|
||||
em_start_locked(struct ifnet *ifp)
|
||||
{
|
||||
int s;
|
||||
struct mbuf *m_head;
|
||||
struct adapter *adapter = ifp->if_softc;
|
||||
|
||||
mtx_assert(&adapter->mtx, MA_OWNED);
|
||||
|
||||
if (!adapter->link_active)
|
||||
return;
|
||||
|
||||
s = splimp();
|
||||
while (ifp->if_snd.ifq_head != NULL) {
|
||||
|
||||
IF_DEQUEUE(&ifp->if_snd, m_head);
|
||||
@ -631,10 +630,20 @@ em_start(struct ifnet *ifp)
|
||||
ifp->if_timer = EM_TX_TIMEOUT;
|
||||
|
||||
}
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
em_start(struct ifnet *ifp)
|
||||
{
|
||||
struct adapter *adapter = ifp->if_softc;
|
||||
|
||||
EM_LOCK(adapter);
|
||||
em_start_locked(ifp);
|
||||
EM_UNLOCK(adapter);
|
||||
return;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* Ioctl entry point
|
||||
*
|
||||
@ -647,11 +656,10 @@ em_start(struct ifnet *ifp)
|
||||
static int
|
||||
em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
{
|
||||
int s, mask, error = 0;
|
||||
int mask, error = 0;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
struct adapter * adapter = ifp->if_softc;
|
||||
|
||||
s = splimp();
|
||||
switch (command) {
|
||||
case SIOCSIFADDR:
|
||||
case SIOCGIFADDR:
|
||||
@ -663,19 +671,22 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
if (ifr->ifr_mtu > MAX_JUMBO_FRAME_SIZE - ETHER_HDR_LEN) {
|
||||
error = EINVAL;
|
||||
} else {
|
||||
EM_LOCK(adapter);
|
||||
ifp->if_mtu = ifr->ifr_mtu;
|
||||
adapter->hw.max_frame_size =
|
||||
ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
|
||||
em_init(adapter);
|
||||
em_init_locked(adapter);
|
||||
EM_UNLOCK(adapter);
|
||||
}
|
||||
break;
|
||||
case SIOCSIFFLAGS:
|
||||
IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)");
|
||||
EM_LOCK(adapter);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (!(ifp->if_flags & IFF_RUNNING)) {
|
||||
bcopy(IF_LLADDR(ifp), adapter->hw.mac_addr,
|
||||
ETHER_ADDR_LEN);
|
||||
em_init(adapter);
|
||||
em_init_locked(adapter);
|
||||
}
|
||||
|
||||
em_disable_promisc(adapter);
|
||||
@ -685,11 +696,13 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
em_stop(adapter);
|
||||
}
|
||||
}
|
||||
EM_UNLOCK(adapter);
|
||||
break;
|
||||
case SIOCADDMULTI:
|
||||
case SIOCDELMULTI:
|
||||
IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI");
|
||||
if (ifp->if_flags & IFF_RUNNING) {
|
||||
EM_LOCK(adapter);
|
||||
em_disable_intr(adapter);
|
||||
em_set_multi(adapter);
|
||||
if (adapter->hw.mac_type == em_82542_rev2_0) {
|
||||
@ -699,6 +712,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
if (!(ifp->if_ipending & IFF_POLLING))
|
||||
#endif
|
||||
em_enable_intr(adapter);
|
||||
EM_UNLOCK(adapter);
|
||||
}
|
||||
break;
|
||||
case SIOCSIFMEDIA:
|
||||
@ -723,7 +737,6 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
error = EINVAL;
|
||||
}
|
||||
|
||||
splx(s);
|
||||
return(error);
|
||||
}
|
||||
|
||||
@ -771,15 +784,13 @@ em_watchdog(struct ifnet *ifp)
|
||||
**********************************************************************/
|
||||
|
||||
static void
|
||||
em_init(void *arg)
|
||||
em_init_locked(struct adapter * adapter)
|
||||
{
|
||||
int s;
|
||||
struct ifnet *ifp;
|
||||
struct adapter * adapter = arg;
|
||||
|
||||
INIT_DEBUGOUT("em_init: begin");
|
||||
|
||||
s = splimp();
|
||||
mtx_assert(&adapter->mtx, MA_OWNED);
|
||||
|
||||
em_stop(adapter);
|
||||
|
||||
@ -787,7 +798,6 @@ em_init(void *arg)
|
||||
if (em_hardware_init(adapter)) {
|
||||
printf("em%d: Unable to initialize the hardware\n",
|
||||
adapter->unit);
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -798,7 +808,6 @@ em_init(void *arg)
|
||||
printf("em%d: Could not setup transmit structures\n",
|
||||
adapter->unit);
|
||||
em_stop(adapter);
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
em_initialize_transmit_unit(adapter);
|
||||
@ -811,7 +820,6 @@ em_init(void *arg)
|
||||
printf("em%d: Could not setup receive structures\n",
|
||||
adapter->unit);
|
||||
em_stop(adapter);
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
em_initialize_receive_unit(adapter);
|
||||
@ -827,7 +835,7 @@ em_init(void *arg)
|
||||
ifp->if_hwassist = 0;
|
||||
}
|
||||
|
||||
adapter->timer_handle = timeout(em_local_timer, adapter, 2*hz);
|
||||
callout_reset(&adapter->timer, 2*hz, em_local_timer, adapter);
|
||||
em_clear_hw_cntrs(&adapter->hw);
|
||||
#ifdef DEVICE_POLLING
|
||||
/*
|
||||
@ -840,7 +848,17 @@ em_init(void *arg)
|
||||
#endif /* DEVICE_POLLING */
|
||||
em_enable_intr(adapter);
|
||||
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
em_init(void *arg)
|
||||
{
|
||||
struct adapter * adapter = arg;
|
||||
|
||||
EM_LOCK(adapter);
|
||||
em_init_locked(adapter);
|
||||
EM_UNLOCK(adapter);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -849,11 +867,13 @@ em_init(void *arg)
|
||||
static poll_handler_t em_poll;
|
||||
|
||||
static void
|
||||
em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
|
||||
em_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
|
||||
{
|
||||
struct adapter *adapter = ifp->if_softc;
|
||||
u_int32_t reg_icr;
|
||||
|
||||
mtx_assert(&adapter->mtx, MA_OWNED);
|
||||
|
||||
if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */
|
||||
em_enable_intr(adapter);
|
||||
return;
|
||||
@ -861,11 +881,11 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
|
||||
if (cmd == POLL_AND_CHECK_STATUS) {
|
||||
reg_icr = E1000_READ_REG(&adapter->hw, ICR);
|
||||
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
|
||||
untimeout(em_local_timer, adapter, adapter->timer_handle);
|
||||
callout_stop(&adapter->timer);
|
||||
adapter->hw.get_link_status = 1;
|
||||
em_check_for_link(&adapter->hw);
|
||||
em_print_link_status(adapter);
|
||||
adapter->timer_handle = timeout(em_local_timer, adapter, 2*hz);
|
||||
callout_reset(&adapter->timer, 2*hz, em_local_timer, adapter);
|
||||
}
|
||||
}
|
||||
if (ifp->if_flags & IFF_RUNNING) {
|
||||
@ -874,7 +894,17 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
|
||||
}
|
||||
|
||||
if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL)
|
||||
em_start(ifp);
|
||||
em_start_locked(ifp);
|
||||
}
|
||||
|
||||
static void
|
||||
em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
|
||||
{
|
||||
struct adapter *adapter = ifp->if_softc;
|
||||
|
||||
EM_LOCK(adapter);
|
||||
em_poll_locked(ifp, cmd, count);
|
||||
EM_UNLOCK(adapter);
|
||||
}
|
||||
#endif /* DEVICE_POLLING */
|
||||
|
||||
@ -891,33 +921,37 @@ em_intr(void *arg)
|
||||
struct ifnet *ifp;
|
||||
struct adapter *adapter = arg;
|
||||
|
||||
EM_LOCK(adapter);
|
||||
|
||||
ifp = &adapter->interface_data.ac_if;
|
||||
|
||||
#ifdef DEVICE_POLLING
|
||||
if (ifp->if_ipending & IFF_POLLING)
|
||||
if (ifp->if_ipending & IFF_POLLING) {
|
||||
EM_UNLOCK(adapter);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ether_poll_register(em_poll, ifp)) {
|
||||
em_disable_intr(adapter);
|
||||
em_poll(ifp, 0, 1);
|
||||
EM_UNLOCK(adapter);
|
||||
return;
|
||||
}
|
||||
#endif /* DEVICE_POLLING */
|
||||
|
||||
reg_icr = E1000_READ_REG(&adapter->hw, ICR);
|
||||
if (!reg_icr) {
|
||||
EM_UNLOCK(adapter);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Link status change */
|
||||
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
|
||||
untimeout(em_local_timer, adapter,
|
||||
adapter->timer_handle);
|
||||
callout_stop(&adapter->timer);
|
||||
adapter->hw.get_link_status = 1;
|
||||
em_check_for_link(&adapter->hw);
|
||||
em_print_link_status(adapter);
|
||||
adapter->timer_handle =
|
||||
timeout(em_local_timer, adapter, 2*hz);
|
||||
callout_reset(&adapter->timer, 2*hz, em_local_timer, adapter);
|
||||
}
|
||||
|
||||
while (loop_cnt > 0) {
|
||||
@ -929,8 +963,9 @@ em_intr(void *arg)
|
||||
}
|
||||
|
||||
if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL)
|
||||
em_start(ifp);
|
||||
em_start_locked(ifp);
|
||||
|
||||
EM_UNLOCK(adapter);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1270,7 +1305,6 @@ em_encap(struct adapter *adapter, struct mbuf *m_head)
|
||||
static void
|
||||
em_82547_move_tail(void *arg)
|
||||
{
|
||||
int s;
|
||||
struct adapter *adapter = arg;
|
||||
uint16_t hw_tdt;
|
||||
uint16_t sw_tdt;
|
||||
@ -1278,7 +1312,7 @@ em_82547_move_tail(void *arg)
|
||||
uint16_t length = 0;
|
||||
boolean_t eop = 0;
|
||||
|
||||
s = splimp();
|
||||
EM_LOCK(adapter);
|
||||
hw_tdt = E1000_READ_REG(&adapter->hw, TDT);
|
||||
sw_tdt = adapter->next_avail_tx_desc;
|
||||
|
||||
@ -1292,20 +1326,16 @@ em_82547_move_tail(void *arg)
|
||||
if(eop) {
|
||||
if (em_82547_fifo_workaround(adapter, length)) {
|
||||
adapter->tx_fifo_wrk++;
|
||||
adapter->tx_fifo_timer_handle =
|
||||
timeout(em_82547_move_tail,
|
||||
adapter, 1);
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
E1000_WRITE_REG(&adapter->hw, TDT, hw_tdt);
|
||||
em_82547_update_fifo_head(adapter, length);
|
||||
length = 0;
|
||||
callout_reset(&adapter->tx_fifo_timer, 1,
|
||||
em_82547_move_tail, adapter);
|
||||
break;
|
||||
}
|
||||
E1000_WRITE_REG(&adapter->hw, TDT, hw_tdt);
|
||||
em_82547_update_fifo_head(adapter, length);
|
||||
length = 0;
|
||||
}
|
||||
}
|
||||
splx(s);
|
||||
EM_UNLOCK(adapter);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1494,12 +1524,11 @@ em_set_multi(struct adapter * adapter)
|
||||
static void
|
||||
em_local_timer(void *arg)
|
||||
{
|
||||
int s;
|
||||
struct ifnet *ifp;
|
||||
struct adapter * adapter = arg;
|
||||
ifp = &adapter->interface_data.ac_if;
|
||||
|
||||
s = splimp();
|
||||
EM_LOCK(adapter);
|
||||
|
||||
em_check_for_link(&adapter->hw);
|
||||
em_print_link_status(adapter);
|
||||
@ -1509,9 +1538,9 @@ em_local_timer(void *arg)
|
||||
}
|
||||
em_smartspeed(adapter);
|
||||
|
||||
adapter->timer_handle = timeout(em_local_timer, adapter, 2*hz);
|
||||
callout_reset(&adapter->timer, 2*hz, em_local_timer, adapter);
|
||||
|
||||
splx(s);
|
||||
EM_UNLOCK(adapter);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1557,12 +1586,13 @@ em_stop(void *arg)
|
||||
struct adapter * adapter = arg;
|
||||
ifp = &adapter->interface_data.ac_if;
|
||||
|
||||
mtx_assert(&adapter->mtx, MA_OWNED);
|
||||
|
||||
INIT_DEBUGOUT("em_stop: begin");
|
||||
em_disable_intr(adapter);
|
||||
em_reset_hw(&adapter->hw);
|
||||
untimeout(em_local_timer, adapter, adapter->timer_handle);
|
||||
untimeout(em_82547_move_tail, adapter,
|
||||
adapter->tx_fifo_timer_handle);
|
||||
callout_stop(&adapter->timer);
|
||||
callout_stop(&adapter->tx_fifo_timer);
|
||||
em_free_transmit_structures(adapter);
|
||||
em_free_receive_structures(adapter);
|
||||
|
||||
@ -1671,7 +1701,8 @@ em_allocate_pci_resources(struct adapter * adapter)
|
||||
adapter->unit);
|
||||
return(ENXIO);
|
||||
}
|
||||
if (bus_setup_intr(dev, adapter->res_interrupt, INTR_TYPE_NET,
|
||||
if (bus_setup_intr(dev, adapter->res_interrupt,
|
||||
INTR_TYPE_NET /*| INTR_MPSAFE*/,
|
||||
(void (*)(void *)) em_intr, adapter,
|
||||
&adapter->int_handler_tag)) {
|
||||
printf("em%d: Error registering interrupt handler!\n",
|
||||
@ -2265,16 +2296,16 @@ em_transmit_checksum_setup(struct adapter * adapter,
|
||||
static void
|
||||
em_clean_transmit_interrupts(struct adapter * adapter)
|
||||
{
|
||||
int s;
|
||||
int i, num_avail;
|
||||
struct em_buffer *tx_buffer;
|
||||
struct em_tx_desc *tx_desc;
|
||||
struct ifnet *ifp = &adapter->interface_data.ac_if;
|
||||
|
||||
mtx_assert(&adapter->mtx, MA_OWNED);
|
||||
|
||||
if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
|
||||
return;
|
||||
|
||||
s = splimp();
|
||||
#ifdef DBG_STATS
|
||||
adapter->clean_tx_interrupts++;
|
||||
#endif
|
||||
@ -2323,7 +2354,6 @@ em_clean_transmit_interrupts(struct adapter * adapter)
|
||||
ifp->if_timer = EM_TX_TIMEOUT;
|
||||
}
|
||||
adapter->num_tx_desc_avail = num_avail;
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2627,6 +2657,8 @@ em_process_receive_interrupts(struct adapter * adapter, int count)
|
||||
/* Pointer to the receive descriptor being examined. */
|
||||
struct em_rx_desc *current_desc;
|
||||
|
||||
mtx_assert(&adapter->mtx, MA_OWNED);
|
||||
|
||||
ifp = &adapter->interface_data.ac_if;
|
||||
i = adapter->next_rx_desc_to_check;
|
||||
current_desc = &adapter->rx_desc_base[i];
|
||||
@ -2731,8 +2763,11 @@ em_process_receive_interrupts(struct adapter * adapter, int count)
|
||||
E1000_RXD_SPC_VLAN_MASK),
|
||||
adapter->fmp = NULL);
|
||||
|
||||
if (adapter->fmp != NULL)
|
||||
if (adapter->fmp != NULL) {
|
||||
EM_UNLOCK(adapter);
|
||||
(*ifp->if_input)(ifp, adapter->fmp);
|
||||
EM_LOCK(adapter);
|
||||
}
|
||||
#endif
|
||||
adapter->fmp = NULL;
|
||||
adapter->lmp = NULL;
|
||||
|
@ -340,10 +340,11 @@ struct adapter {
|
||||
struct resource *res_interrupt;
|
||||
void *int_handler_tag;
|
||||
struct ifmedia media;
|
||||
struct callout_handle timer_handle;
|
||||
struct callout_handle tx_fifo_timer_handle;
|
||||
struct callout timer;
|
||||
struct callout tx_fifo_timer;
|
||||
int io_rid;
|
||||
u_int8_t unit;
|
||||
struct mtx mtx;
|
||||
|
||||
/* Info about the board itself */
|
||||
u_int32_t part_num;
|
||||
@ -424,4 +425,7 @@ struct adapter {
|
||||
struct em_hw_stats stats;
|
||||
};
|
||||
|
||||
#define EM_LOCK(_sc) mtx_lock(&(_sc)->mtx)
|
||||
#define EM_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
|
||||
|
||||
#endif /* _EM_H_DEFINED_ */
|
||||
|
Loading…
Reference in New Issue
Block a user