Next | Prev | Up | Top | Contents | Index

ifnet Drivers

ifnet-based networking device drivers that queue or dequeue packets on the ipintrq or if_snd queue must be modified to use the appropriate IFNET_LOCK macro. Definitions of the new locking macros are in net/if.h in an IRIX 5.3 system. Refer to Chapter 9, "Writing Network Device Drivers," for more information.


Context diff of Token Ring ifnet Driver

The following fragment illustrates the changes made in one such driver (this is for the token ring, a driver that was otherwise unchanged during these modifications).

>>> add include file for capabilities.
*** 105,110 ****
--- 105,111 ----
  #endif
  #include "sys/dlsap_register.h"
  #endif    /* _IRIX4 */
+ #include "sys/capability.h"
  
  #ifdef QDBG
  struct tr_qs fvqs;

Board Initialization

This is in the board initialization routine, where the interface lock has been set by the caller.

*** 547,552 ****
--- 548,554 ----
  {
      struct fv_info *fv = &fv_info[unit];
      struct ifnet *ifp = &fv->fv_if;
+     ASSERT(IFNET_ISLOCKED(ifp));
  
      if ((ifp->if_flags & IFF_RUNNING) != 0) {
          DP(("if_fvinit%d: already running\n", fv->fv_unit));

>>> also in the init routine.  Release the interface lock 
>>> before sleeping, reacquire it after the sleep returns.
*** 553,560 ****
          return(0);
      }
  
!     if (fv->fv_state < FV_STATE_OK)
          sleep((caddr_t)&fv->fv_state, PZERO|PCATCH);
      if (fv->fv_state != FV_STATE_OK) {
          return(EIO);
      }
--- 555,565 ----
          return(0);
      }
  
!     if (fv->fv_state < FV_STATE_OK) {
!         IFNET_UNLOCKNOSPL(ifp);
          sleep((caddr_t)&fv->fv_state, PZERO|PCATCH);
+         IFNET_LOCKNOSPL(ifp);
+     }
      if (fv->fv_state != FV_STATE_OK) {
          return(EIO);
      }

>>> this is in the driver's ioctl routine. ASSERT that the >>> ioctl routine was called with interface lock held.
*** 894,899 ****
--- 899,905 ----
      struct fv_info *fv = &fv_info[ifp->if_unit];
  
      ASSERT(&fv->fv_ac == (struct arpcom*)ifp);
+     ASSERT(IFNET_ISLOCKED(ifp));
      switch (cmd) {
      case SIOCSIFADDR: {
          struct ifaddr *ifa = (struct ifaddr *)data;

>>> TrIRIX change for privilege check.
*** 1167,1173 ****
      case SIOC_TR_ARM: {
          TR_SIOC *sioc = (TR_SIOC*)data;
  
!         if (!suser()) {
              error = EPERM;
              break;
          }
--- 1173,1179 ----
      case SIOC_TR_ARM: {
          TR_SIOC *sioc = (TR_SIOC*)data;
  
!         if (!_CAP_ABLE(CAP_NETWORK_MGT)) {
              error = EPERM;
              break;
          }

Interrupt Handler

This is in the interrupt handler. Acquire the interface lock. fv is a unit info structure pointer, one element of which is the pointer to struct ifnet, the interface structure shared with IP.

*** 1231,1236 ****
--- 1237,1243 ----
          printf("fv%d: early interrupt\n", unit);
          goto fvintr_ret;
      }
+     IFNET_LOCKNOSPL(&fv->fv_if);
      QDBGUP(fvints.tot,1);
      mem = fv->fv_mem;
  iloop:

 More of the interrupt handler.  Free the lock as we exit.
*** 1237,1242 ****
--- 1244,1250 ----
      /* get the type of interrupt */
      cmdsts = io->sifcmd_stat;
      if ((cmdsts&TR_STAT_INTR) == 0) {
+         IFNET_UNLOCKNOSPL(&fv->fv_if);
          goto fvintr_ret;
      }
      found++;

>>> still more of the interrupt handler.
*** 1300,1305 ****
--- 1308,1314 ----
          fv->fv_state = FV_STATE_SICK;
          }
          QDBGUP(fvints.buf,1);
+         IFNET_UNLOCKNOSPL(&fv->fv_if);
          goto fvintr_ret;
  
      case TR_INT_SCB_CLEAR:

>>> frame receive handler.  Lock the IP input queue to add a packet to it.
*** 2031,2044 ****
  
      switch (port) {
      case ETHERTYPE_IP:
-         schednetisr(NETISR_IP);
          ifq = &ipintrq;
                 if (IF_QFULL(ifq)) {
              IF_DROP(ifq);
              fv->fv_if.if_iqdrops++;
              goto drop;
          }
!                IF_ENQUEUE(ifq, m0);
          goto read_ret;
      case ETHERTYPE_ARP:
          if (sri) {
--- 2041,2057 ----
  
      switch (port) {
      case ETHERTYPE_IP:
          ifq = &ipintrq;
+         IFQ_LOCK(ifq);
                 if (IF_QFULL(ifq)) {
              IF_DROP(ifq);
              fv->fv_if.if_iqdrops++;
+             IFQ_UNLOCK(ifq);
              goto drop;
          }
!         IF_ENQUEUE_NOLOCK(ifq, m0);
!         IFQ_UNLOCK(ifq);
!         schednetisr(NETISR_IP);
          goto read_ret;
      case ETHERTYPE_ARP:
          if (sri) {

>>> Output routine, assert caller has if structure 
>>> locked for us.
*** 2269,2274 ****
--- 2282,2288 ----
      ASSERT((ifp->if_unit >= 0) && (ifp->if_unit < FV_MAXBD));
      fv = &fv_info[ifp->if_unit];
      ASSERT(0 != fv->FVIO && ifp == &fv->fv_if);
+     ASSERT(IFNET_ISLOCKED(ifp));
  
      /* 2: make sure board has been initialized properly */
      if (fv->fv_state != FV_STATE_OK || iff_dead(ifp->if_flags)) {

>>> close routine.  ASSERT caller locked interface, 
>>> release and reacquire lock around sleep.
*** 3750,3761 ****
--- 3765,3780 ----
      FVMEM *mem = fv->fv_mem;
  
      DP(("fv%d: close%\n", fv->fv_unit));
+     ASSERT(IFNET_ISLOCKED(&fv->fv_if));
+ 
      if (fv->fv_state != FV_STATE_OK)
          goto close_ret;
  
      while ((fv->cmd_Flags[TR_CMD_CLOSE]&CMD_BUSY) != 0) {
          fv->cmd_Flags[TR_CMD_CLOSE] |= CMD_PENDING;
+         IFNET_UNLOCKNOSPL(&fv->fv_if);
          sleep((caddr_t)&fv->cmd_Flags[TR_CMD_CLOSE],PZERO|PCATCH);
+         IFNET_LOCKNOSPL(&fv->fv_if);
      }
      fv->cmd_Flags[TR_CMD_CLOSE] |= CMD_BUSY;
  

>>> later in the close routine, another release/reacquire 
    around sleep.
*** 3776,3782 ****
--- 3795,3803 ----
      io->sifcmd_stat = TR_CMD_INT_ADAPT | TR_CMD_EXECUTE | 
                  TR_CMD_SCB_REQUEST | TR_STAT_INTR;
  
+ IFNET_UNLOCKNOSPL(&fv->fv_if);
  sleep((caddr_t)&fv->cmd_Status[TR_CMD_CLOSE], PZERO|PCATCH);
+ IFNET_LOCKNOSPL(&fv->fv_if);
  if (fv->cmd_Status[TR_CMD_CLOSE] == 0) {
      fv->fv_state = FV_STATE_CLOSE;
      fv->fv_if.if_flags &= ~(IFF_UP|IFF_RUNNING);

mbuf Manager Changes

>>> delete the mbinit() call, no longer needed.
*** 3174,3183 ****
      IDP(("fv%u: IVEC set!\n", unit));
  #endif /* !_IRIX4 */
  
-     /* 3: start the mbufs */
-     mbinit();
  
!     /* 4: setup PRIVATE data.*/
      /* TBD: allocate mcast filter table.
       *    Probably, ALLMULTI(via ffffffff) should be used        *    and locally calculate correct filter.
--- 3174,3181 ----
      IDP(("fv%u: IVEC set!\n", unit));
  #endif /* !_IRIX4 */
  
  
!     /* setup PRIVATE data.*/
      /* TBD: allocate mcast filter table.
       *    Probably, ALLMULTI(via ffffffff) should be used 
       *    and locally calculate correct filter.

Next | Prev | Up | Top | Contents | Index