📄 i2o_lan.c
字号:
* except SendPost and ReceivePost. */static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, struct i2o_message *m){ u32 *msg = (u32 *)m; u8 unit = (u8)(msg[2]>>16); // InitiatorContext struct net_device *dev = i2o_landevs[unit]; if ((msg[4] >> 24) != I2O_REPLY_STATUS_SUCCESS) { if (i2o_lan_handle_status(dev, msg)) return; /* In other error cases just report and continue */ i2o_report_status(KERN_INFO, dev->name, msg); }#ifdef DRIVERDEBUG i2o_report_status(KERN_INFO, dev->name, msg);#endif switch (msg[1] >> 24) { case LAN_RESET: case LAN_SUSPEND: /* default reply without payload */ break; case I2O_CMD_UTIL_EVT_REGISTER: case I2O_CMD_UTIL_EVT_ACK: i2o_lan_handle_event(dev, msg); break; case I2O_CMD_UTIL_PARAMS_SET: /* default reply, results in ReplyPayload (not examined) */ switch (msg[3] >> 16) { case 1: dprintk(KERN_INFO "%s: Reply to set MAC filter mask.\n", dev->name); break; case 2: dprintk(KERN_INFO "%s: Reply to set MAC table.\n", dev->name); break; default: printk(KERN_WARNING "%s: Bad group 0x%04X\n", dev->name,msg[3] >> 16); } break; default: printk(KERN_ERR "%s: No handler for the reply.\n", dev->name); i2o_report_status(KERN_INFO, dev->name, msg); }}/* Functions used by the above callback functions:=================================================*//* * i2o_lan_release_buckets(): Free unused buckets (sk_buffs). */static void i2o_lan_release_buckets(struct net_device *dev, u32 *msg){ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; u8 trl_elem_size = (u8)(msg[3]>>8 & 0x000000FF); u8 trl_count = (u8)(msg[3] & 0x000000FF); u32 *pskb = &msg[6]; while (trl_count--) { dprintk(KERN_DEBUG "%s: Releasing unused rx skb %p (trl_count=%d).\n", dev->name, (struct sk_buff*)(*pskb),trl_count+1); dev_kfree_skb_irq((struct sk_buff *)(*pskb)); pskb += 1 + trl_elem_size; atomic_dec(&priv->buckets_out); }}/* * i2o_lan_event_reply(): Handle events. */static void i2o_lan_handle_event(struct net_device *dev, u32 *msg){ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; struct i2o_controller *iop = i2o_dev->controller; u32 max_evt_data_size =iop->status_block->inbound_frame_size-5; struct i2o_reply { u32 header[4]; u32 evt_indicator; u32 data[max_evt_data_size]; } *evt = (struct i2o_reply *)msg; int evt_data_len = ((msg[0]>>16) - 5) * 4; /* real size*/ printk(KERN_INFO "%s: I2O event - ", dev->name); if (msg[1]>>24 == I2O_CMD_UTIL_EVT_ACK) { printk("Event acknowledgement reply.\n"); return; } /* Else evt->function == I2O_CMD_UTIL_EVT_REGISTER) */ switch (evt->evt_indicator) { case I2O_EVT_IND_STATE_CHANGE: { struct state_data { u16 status; u8 state; u8 data; } *evt_data = (struct state_data *)(evt->data[0]); printk("State chance 0x%08x.\n", evt->data[0]); /* If the DDM is in error state, recovery may be * possible if status = Transmit or Receive Control * Unit Inoperable. */ if (evt_data->state==0x05 && evt_data->status==0x0003) i2o_lan_reset(dev); break; } case I2O_EVT_IND_FIELD_MODIFIED: { u16 *work16 = (u16 *)evt->data; printk("Group 0x%04x, field %d changed.\n", work16[0], work16[1]); break; } case I2O_EVT_IND_VENDOR_EVT: { int i; printk("Vendor event:\n"); for (i = 0; i < evt_data_len / 4; i++) printk(" 0x%08x\n", evt->data[i]); break; } case I2O_EVT_IND_DEVICE_RESET: /* Spec 2.0 p. 6-121: * The event of _DEVICE_RESET should also be responded */ printk("Device reset.\n"); if (i2o_event_ack(iop, msg) < 0) printk("%s: Event Acknowledge timeout.\n", dev->name); break;#if 0 case I2O_EVT_IND_EVT_MASK_MODIFIED: printk("Event mask modified, 0x%08x.\n", evt->data[0]); break; case I2O_EVT_IND_GENERAL_WARNING: printk("General warning 0x%04x.\n", evt->data[0]); break; case I2O_EVT_IND_CONFIGURATION_FLAG: printk("Configuration requested.\n"); break; case I2O_EVT_IND_CAPABILITY_CHANGE: printk("Capability change 0x%04x.\n", evt->data[0]); break; case I2O_EVT_IND_DEVICE_STATE: printk("Device state changed 0x%08x.\n", evt->data[0]); break;#endif case I2O_LAN_EVT_LINK_DOWN: netif_carrier_off(dev); printk("Link to the physical device is lost.\n"); break; case I2O_LAN_EVT_LINK_UP: netif_carrier_on(dev); printk("Link to the physical device is (re)established.\n"); break; case I2O_LAN_EVT_MEDIA_CHANGE: printk("Media change.\n"); break; default: printk("0x%08x. No handler.\n", evt->evt_indicator); }}/* * i2o_lan_receive_post(): Post buckets to receive packets. */static int i2o_lan_receive_post(struct net_device *dev){ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; struct i2o_controller *iop = i2o_dev->controller; struct sk_buff *skb; u32 m, *msg; u32 bucket_len = (dev->mtu + dev->hard_header_len); u32 total = priv->max_buckets_out - atomic_read(&priv->buckets_out); u32 bucket_count; u32 *sgl_elem; unsigned long flags; /* Send (total/bucket_count) separate I2O requests */ while (total) { m = I2O_POST_READ32(iop); if (m == 0xFFFFFFFF) return -ETIMEDOUT; msg = (u32 *)(iop->mem_offset + m); bucket_count = (total >= priv->sgl_max) ? priv->sgl_max : total; total -= bucket_count; atomic_add(bucket_count, &priv->buckets_out); dprintk(KERN_INFO "%s: Sending %d buckets (size %d) to LAN DDM.\n", dev->name, bucket_count, bucket_len); /* Fill in the header */ __raw_writel(I2O_MESSAGE_SIZE(4 + 3 * bucket_count) | SGL_OFFSET_4, msg); __raw_writel(LAN_RECEIVE_POST<<24 | HOST_TID<<12 | i2o_dev->lct_data.tid, msg+1); __raw_writel(priv->unit << 16 | lan_receive_context, msg+2); __raw_writel(bucket_count, msg+3); sgl_elem = &msg[4]; /* Fill in the payload - contains bucket_count SGL elements */ while (bucket_count--) { spin_lock_irqsave(&priv->fbl_lock, flags); if (priv->i2o_fbl_tail >= 0) skb = priv->i2o_fbl[priv->i2o_fbl_tail--]; else { skb = dev_alloc_skb(bucket_len + 2); if (skb == NULL) { spin_unlock_irqrestore(&priv->fbl_lock, flags); return -ENOMEM; } skb_reserve(skb, 2); } spin_unlock_irqrestore(&priv->fbl_lock, flags); __raw_writel(0x51000000 | bucket_len, sgl_elem); __raw_writel((u32)skb, sgl_elem+1); __raw_writel(virt_to_bus(skb->data), sgl_elem+2); sgl_elem += 3; } /* set LE flag and post */ __raw_writel(__raw_readl(sgl_elem-3) | 0x80000000, (sgl_elem-3)); i2o_post_message(iop, m); } return 0;}/* Functions called from the network stack, and functions called by them:========================================================================*//* * i2o_lan_reset(): Reset the LAN adapter into the operational state and * restore it to full operation. */static int i2o_lan_reset(struct net_device *dev){ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; struct i2o_controller *iop = i2o_dev->controller; u32 msg[5]; dprintk(KERN_INFO "%s: LAN RESET MESSAGE.\n", dev->name); msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0; msg[1] = LAN_RESET<<24 | HOST_TID<<12 | i2o_dev->lct_data.tid; msg[2] = priv->unit << 16 | lan_context; // InitiatorContext msg[3] = 0; // TransactionContext msg[4] = 0; // Keep posted buckets if (i2o_post_this(iop, msg, sizeof(msg)) < 0) return -ETIMEDOUT; return 0;}/* * i2o_lan_suspend(): Put LAN adapter into a safe, non-active state. * IOP replies to any LAN class message with status error_no_data_transfer * / suspended. */static int i2o_lan_suspend(struct net_device *dev){ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; struct i2o_controller *iop = i2o_dev->controller; u32 msg[5]; dprintk(KERN_INFO "%s: LAN SUSPEND MESSAGE.\n", dev->name); msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0; msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->lct_data.tid; msg[2] = priv->unit << 16 | lan_context; // InitiatorContext msg[3] = 0; // TransactionContext msg[4] = 1 << 16; // return posted buckets if (i2o_post_this(iop, msg, sizeof(msg)) < 0) return -ETIMEDOUT; return 0;}/* * i2o_set_ddm_parameters: * These settings are done to ensure proper initial values for DDM. * They can be changed via proc file system or vai configuration utility. */static void i2o_set_ddm_parameters(struct net_device *dev){ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; struct i2o_controller *iop = i2o_dev->controller; u32 val; /* * When PacketOrphanlimit is set to the maximum packet length, * the packets will never be split into two separate buckets */ val = dev->mtu + dev->hard_header_len; if (i2o_set_scalar(iop, i2o_dev->lct_data.tid, 0x0004, 2, &val, sizeof(val)) < 0) printk(KERN_WARNING "%s: Unable to set PacketOrphanLimit.\n", dev->name); else dprintk(KERN_INFO "%s: PacketOrphanLimit set to %d.\n", dev->name, val); /* When RxMaxPacketsBucket = 1, DDM puts only one packet into bucket */ val = 1; if (i2o_set_scalar(iop, i2o_dev->lct_data.tid, 0x0008, 4, &val, sizeof(val)) <0) printk(KERN_WARNING "%s: Unable to set RxMaxPacketsBucket.\n", dev->name); else dprintk(KERN_INFO "%s: RxMaxPacketsBucket set to %d.\n", dev->name, val); return;}/* Functions called from the network stack:==========================================*//* * i2o_lan_open(): Open the device to send/receive packets via * the network device. */static int i2o_lan_open(struct net_device *dev){ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; struct i2o_controller *iop = i2o_dev->controller; u32 mc_addr_group[64]; MOD_INC_USE_COUNT; if (i2o_claim_device(i2o_dev, &i2o_lan_handler)) { printk(KERN_WARNING "%s: Unable to claim the I2O LAN device.\n", dev->name); MOD_DEC_USE_COUNT; return -EAGAIN; } dprintk(KERN_INFO "%s: I2O LAN device (tid=%d) claimed by LAN OSM.\n", dev->name, i2o_dev->lct_data.tid); if (i2o_event_register(iop, i2o_dev->lct_data.tid, priv->unit << 16 | lan_context, 0, priv->i2o_event_mask) < 0) printk(KERN_WARNING "%s: Unable to set the event mask.\n", dev->name); i2o_lan_reset(dev); /* Get the max number of multicast addresses */ if (i2o_query_scalar(iop, i2o_dev->lct_data.tid, 0x0001, -1, &mc_addr_group, sizeof(mc_addr_group)) < 0 ) { printk(KERN_WARNING "%s: Unable to query LAN_MAC_ADDRESS group.\n", dev->name); MOD_DEC_USE_COUNT; return -EAGAIN; } priv->max_size_mc_table = mc_addr_group[8]; /* Malloc space for free bucket list to resuse reveive post buckets */ priv->i2o_fbl = kmalloc(priv->max_buckets_out * sizeof(struct sk_buff *), GFP_KERNEL); if (priv->i2o_fbl == NULL) { MOD_DEC_USE_COUNT; return -ENOMEM; } priv->i2o_fbl_tail = -1; priv->send_active = 0; i2o_set_ddm_parameters(dev); i2o_lan_receive_post(dev); netif_start_queue(dev); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -