Skip to content

Commit

Permalink
eHEA: Introducing support vor DLPAR memory add
Browse files Browse the repository at this point in the history
This patch adds support for DLPAR memory add to the eHEA driver. To detect
whether memory was added the driver uses its own memory mapping table and
checks for kernel addresses whether they're located in already known memory
sections. If not the function ehea_rereg_mrs() is triggered which performs
a rebuild of the mapping table and a re-registration of the global memory
region.

Signed-off-by: Thomas Klein <tklein@de.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Thomas Klein authored and Jeff Garzik committed Jul 16, 2007
1 parent 5be8084 commit 44c8215
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 65 deletions.
23 changes: 18 additions & 5 deletions drivers/net/ehea/ehea.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@
#include <asm/io.h>

#define DRV_NAME "ehea"
#define DRV_VERSION "EHEA_0067"
#define DRV_VERSION "EHEA_0070"

/* EHEA capability flags */
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
#define DLPAR_MEM_ADD 2
#define DLPAR_MEM_REM 4
#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM)
#define DLPAR_MEM_ADD 2
#define DLPAR_MEM_REM 4
#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM)

#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
Expand Down Expand Up @@ -113,6 +113,8 @@
/* Memory Regions */
#define EHEA_MR_ACC_CTRL 0x00800000

#define EHEA_BUSMAP_START 0x8000000000000000ULL

#define EHEA_WATCH_DOG_TIMEOUT 10*HZ

/* utility functions */
Expand Down Expand Up @@ -186,6 +188,12 @@ struct h_epas {
set to 0 if unused */
};

struct ehea_busmap {
unsigned int entries; /* total number of entries */
unsigned int valid_sections; /* number of valid sections */
u64 *vaddr;
};

struct ehea_qp;
struct ehea_cq;
struct ehea_eq;
Expand Down Expand Up @@ -382,6 +390,8 @@ struct ehea_adapter {
struct ehea_mr mr;
u32 pd; /* protection domain */
u64 max_mc_mac; /* max number of multicast mac addresses */
int active_ports;
struct list_head list;
};


Expand Down Expand Up @@ -431,6 +441,9 @@ struct port_res_cfg {
int max_entries_rq3;
};

enum ehea_flag_bits {
__EHEA_STOP_XFER
};

void ehea_set_ethtool_ops(struct net_device *netdev);
int ehea_sense_port_attr(struct ehea_port *port);
Expand Down
144 changes: 130 additions & 14 deletions drivers/net/ehea/ehea_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue "
MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");

static int port_name_cnt = 0;
static LIST_HEAD(adapter_list);
u64 ehea_driver_flags = 0;
struct workqueue_struct *ehea_driver_wq;
struct work_struct ehea_rereg_mr_task;


static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
const struct of_device_id *id);
Expand Down Expand Up @@ -238,13 +243,17 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
| EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
rwqe->sg_list[0].vaddr = (u64)skb->data;
rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
rwqe->sg_list[0].len = packet_size;
rwqe->data_segments = 1;

index++;
index &= max_index_mask;

if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
goto out;
}

q_skba->index = index;

/* Ring doorbell */
Expand All @@ -253,7 +262,7 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
ehea_update_rq2a(pr->qp, i);
else
ehea_update_rq3a(pr->qp, i);

out:
return ret;
}

Expand Down Expand Up @@ -1321,7 +1330,7 @@ static void write_swqe2_TSO(struct sk_buff *skb,
sg1entry->len = skb_data_size - headersize;

tmp_addr = (u64)(skb->data + headersize);
sg1entry->vaddr = tmp_addr;
sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
swqe->descriptors++;
}
} else
Expand Down Expand Up @@ -1352,7 +1361,7 @@ static void write_swqe2_nonTSO(struct sk_buff *skb,
sg1entry->l_key = lkey;
sg1entry->len = skb_data_size - SWQE2_MAX_IMM;
tmp_addr = (u64)(skb->data + SWQE2_MAX_IMM);
sg1entry->vaddr = tmp_addr;
sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
swqe->descriptors++;
}
} else {
Expand Down Expand Up @@ -1391,7 +1400,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
sg1entry->len = frag->size;
tmp_addr = (u64)(page_address(frag->page)
+ frag->page_offset);
sg1entry->vaddr = tmp_addr;
sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
swqe->descriptors++;
sg1entry_contains_frag_data = 1;
}
Expand All @@ -1406,7 +1415,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,

tmp_addr = (u64)(page_address(frag->page)
+ frag->page_offset);
sgentry->vaddr = tmp_addr;
sgentry->vaddr = ehea_map_vaddr(tmp_addr);
swqe->descriptors++;
}
}
Expand Down Expand Up @@ -1878,6 +1887,9 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
ehea_dump(swqe, 512, "swqe");
}

if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
goto out;

ehea_post_swqe(pr->qp, swqe);
pr->tx_packets++;

Expand All @@ -1892,7 +1904,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
dev->trans_start = jiffies;
spin_unlock(&pr->xmit_lock);

out:
return NETDEV_TX_OK;
}

Expand Down Expand Up @@ -2220,6 +2232,9 @@ static int ehea_up(struct net_device *dev)
out_clean_pr:
ehea_clean_all_portres(port);
out:
if (ret)
ehea_info("Failed starting %s. ret=%i", dev->name, ret);

return ret;
}

Expand Down Expand Up @@ -2259,8 +2274,13 @@ static int ehea_down(struct net_device *dev)
msleep(1);

ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
ret = ehea_clean_all_portres(port);
port->state = EHEA_PORT_DOWN;

ret = ehea_clean_all_portres(port);
if (ret)
ehea_info("Failed freeing resources for %s. ret=%i",
dev->name, ret);

return ret;
}

Expand Down Expand Up @@ -2292,15 +2312,11 @@ static void ehea_reset_port(struct work_struct *work)
netif_stop_queue(dev);
netif_poll_disable(dev);

ret = ehea_down(dev);
if (ret)
ehea_error("ehea_down failed. not all resources are freed");
ehea_down(dev);

ret = ehea_up(dev);
if (ret) {
ehea_error("Reset device %s failed: ret=%d", dev->name, ret);
if (ret)
goto out;
}

if (netif_msg_timer(port))
ehea_info("Device %s resetted successfully", dev->name);
Expand All @@ -2312,6 +2328,88 @@ static void ehea_reset_port(struct work_struct *work)
return;
}

static void ehea_rereg_mrs(struct work_struct *work)
{
int ret, i;
struct ehea_adapter *adapter;

ehea_info("LPAR memory enlarged - re-initializing driver");

list_for_each_entry(adapter, &adapter_list, list)
if (adapter->active_ports) {
/* Shutdown all ports */
for (i = 0; i < EHEA_MAX_PORTS; i++) {
struct ehea_port *port = adapter->port[i];

if (port) {
struct net_device *dev = port->netdev;

if (dev->flags & IFF_UP) {
ehea_info("stopping %s",
dev->name);
down(&port->port_lock);
netif_stop_queue(dev);
netif_poll_disable(dev);
ehea_down(dev);
up(&port->port_lock);
}
}
}

/* Unregister old memory region */
ret = ehea_rem_mr(&adapter->mr);
if (ret) {
ehea_error("unregister MR failed - driver"
" inoperable!");
goto out;
}
}

ehea_destroy_busmap();

ret = ehea_create_busmap();
if (ret)
goto out;

clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags);

list_for_each_entry(adapter, &adapter_list, list)
if (adapter->active_ports) {
/* Register new memory region */
ret = ehea_reg_kernel_mr(adapter, &adapter->mr);
if (ret) {
ehea_error("register MR failed - driver"
" inoperable!");
goto out;
}

/* Restart all ports */
for (i = 0; i < EHEA_MAX_PORTS; i++) {
struct ehea_port *port = adapter->port[i];

if (port) {
struct net_device *dev = port->netdev;

if (dev->flags & IFF_UP) {
ehea_info("restarting %s",
dev->name);
down(&port->port_lock);

ret = ehea_up(dev);
if (!ret) {
netif_poll_enable(dev);
netif_wake_queue(dev);
}

up(&port->port_lock);
}
}
}
}
out:
return;
}

static void ehea_tx_watchdog(struct net_device *dev)
{
struct ehea_port *port = netdev_priv(dev);
Expand Down Expand Up @@ -2573,6 +2671,8 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
ehea_info("%s: Jumbo frames are %sabled", dev->name,
jumbo == 1 ? "en" : "dis");

adapter->active_ports++;

return port;

out_unreg_port:
Expand All @@ -2596,6 +2696,7 @@ static void ehea_shutdown_single_port(struct ehea_port *port)
ehea_unregister_port(port);
kfree(port->mc_list);
free_netdev(port->netdev);
port->adapter->active_ports--;
}

static int ehea_setup_ports(struct ehea_adapter *adapter)
Expand Down Expand Up @@ -2788,6 +2889,8 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
goto out;
}

list_add(&adapter->list, &adapter_list);

adapter->ebus_dev = dev;

adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
Expand Down Expand Up @@ -2891,7 +2994,10 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev)

ehea_destroy_eq(adapter->neq);
ehea_remove_adapter_mr(adapter);
list_del(&adapter->list);

kfree(adapter);

return 0;
}

Expand Down Expand Up @@ -2939,9 +3045,18 @@ int __init ehea_module_init(void)
printk(KERN_INFO "IBM eHEA ethernet device driver (Release %s)\n",
DRV_VERSION);

ehea_driver_wq = create_workqueue("ehea_driver_wq");

INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs);

ret = check_module_parm();
if (ret)
goto out;

ret = ehea_create_busmap();
if (ret)
goto out;

ret = ibmebus_register_driver(&ehea_driver);
if (ret) {
ehea_error("failed registering eHEA device driver on ebus");
Expand All @@ -2965,6 +3080,7 @@ static void __exit ehea_module_exit(void)
{
driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
ibmebus_unregister_driver(&ehea_driver);
ehea_destroy_busmap();
}

module_init(ehea_module_init);
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ehea/ehea_phyp.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ static inline u32 get_longbusy_msecs(int long_busy_ret_code)
}
}

/* Number of pages which can be registered at once by H_REGISTER_HEA_RPAGES */
#define EHEA_MAX_RPAGE 512

/* Notification Event Queue (NEQ) Entry bit masks */
#define NEQE_EVENT_CODE EHEA_BMASK_IBM(2, 7)
#define NEQE_PORTNUM EHEA_BMASK_IBM(32, 47)
Expand Down
Loading

0 comments on commit 44c8215

Please sign in to comment.