diff options
Diffstat (limited to 'drivers/thunderbolt')
| -rw-r--r-- | drivers/thunderbolt/ctl.c | 6 | ||||
| -rw-r--r-- | drivers/thunderbolt/debugfs.c | 2 | ||||
| -rw-r--r-- | drivers/thunderbolt/dma_port.c | 15 | ||||
| -rw-r--r-- | drivers/thunderbolt/dma_test.c | 4 | ||||
| -rw-r--r-- | drivers/thunderbolt/domain.c | 4 | ||||
| -rw-r--r-- | drivers/thunderbolt/icm.c | 6 | ||||
| -rw-r--r-- | drivers/thunderbolt/nhi.c | 4 | ||||
| -rw-r--r-- | drivers/thunderbolt/nvm.c | 2 | ||||
| -rw-r--r-- | drivers/thunderbolt/path.c | 30 | ||||
| -rw-r--r-- | drivers/thunderbolt/property.c | 6 | ||||
| -rw-r--r-- | drivers/thunderbolt/quirks.c | 7 | ||||
| -rw-r--r-- | drivers/thunderbolt/retimer.c | 2 | ||||
| -rw-r--r-- | drivers/thunderbolt/switch.c | 40 | ||||
| -rw-r--r-- | drivers/thunderbolt/tb.c | 4 | ||||
| -rw-r--r-- | drivers/thunderbolt/tb.h | 5 | ||||
| -rw-r--r-- | drivers/thunderbolt/tunnel.c | 10 | ||||
| -rw-r--r-- | drivers/thunderbolt/tunnel.h | 5 | ||||
| -rw-r--r-- | drivers/thunderbolt/usb4_port.c | 2 | ||||
| -rw-r--r-- | drivers/thunderbolt/xdomain.c | 6 |
19 files changed, 81 insertions, 79 deletions
diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c index d7a535671404..b2fd60fc7bcc 100644 --- a/drivers/thunderbolt/ctl.c +++ b/drivers/thunderbolt/ctl.c @@ -89,7 +89,7 @@ struct tb_cfg_request *tb_cfg_request_alloc(void) { struct tb_cfg_request *req; - req = kzalloc(sizeof(*req), GFP_KERNEL); + req = kzalloc_obj(*req); if (!req) return NULL; @@ -333,7 +333,7 @@ static void tb_ctl_pkg_free(struct ctl_pkg *pkg) static struct ctl_pkg *tb_ctl_pkg_alloc(struct tb_ctl *ctl) { - struct ctl_pkg *pkg = kzalloc(sizeof(*pkg), GFP_KERNEL); + struct ctl_pkg *pkg = kzalloc_obj(*pkg); if (!pkg) return NULL; pkg->ctl = ctl; @@ -654,7 +654,7 @@ struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, int index, int timeout_msec, event_cb cb, void *cb_data) { int i; - struct tb_ctl *ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); + struct tb_ctl *ctl = kzalloc_obj(*ctl); if (!ctl) return NULL; diff --git a/drivers/thunderbolt/debugfs.c b/drivers/thunderbolt/debugfs.c index 45266ec72f88..042f6a0d0f7f 100644 --- a/drivers/thunderbolt/debugfs.c +++ b/drivers/thunderbolt/debugfs.c @@ -1657,7 +1657,7 @@ static struct tb_margining *margining_alloc(struct tb_port *port, return NULL; } - margining = kzalloc(sizeof(*margining), GFP_KERNEL); + margining = kzalloc_obj(*margining); if (!margining) return NULL; diff --git a/drivers/thunderbolt/dma_port.c b/drivers/thunderbolt/dma_port.c index dc8ea188a114..c7c2942fa7be 100644 --- a/drivers/thunderbolt/dma_port.c +++ b/drivers/thunderbolt/dma_port.c @@ -55,7 +55,7 @@ struct tb_dma_port { struct tb_switch *sw; u8 port; u32 base; - u8 *buf; + u8 buf[]; }; /* @@ -209,16 +209,10 @@ struct tb_dma_port *dma_port_alloc(struct tb_switch *sw) if (port < 0) return NULL; - dma = kzalloc(sizeof(*dma), GFP_KERNEL); + dma = kzalloc_flex(*dma, buf, MAIL_DATA_DWORDS); if (!dma) return NULL; - dma->buf = kmalloc_array(MAIL_DATA_DWORDS, sizeof(u32), GFP_KERNEL); - if (!dma->buf) { - kfree(dma); - return NULL; - } - dma->sw = sw; dma->port = port; dma->base = DMA_PORT_CAP; @@ -232,10 +226,7 @@ struct tb_dma_port *dma_port_alloc(struct tb_switch *sw) */ void dma_port_free(struct tb_dma_port *dma) { - if (dma) { - kfree(dma->buf); - kfree(dma); - } + kfree(dma); } static int dma_port_wait_for_completion(struct tb_dma_port *dma, diff --git a/drivers/thunderbolt/dma_test.c b/drivers/thunderbolt/dma_test.c index 9e47a63f28e7..b4aa79d482a0 100644 --- a/drivers/thunderbolt/dma_test.c +++ b/drivers/thunderbolt/dma_test.c @@ -267,7 +267,7 @@ static int dma_test_submit_rx(struct dma_test *dt, size_t npackets) struct dma_test_frame *tf; dma_addr_t dma_addr; - tf = kzalloc(sizeof(*tf), GFP_KERNEL); + tf = kzalloc_obj(*tf); if (!tf) return -ENOMEM; @@ -318,7 +318,7 @@ static int dma_test_submit_tx(struct dma_test *dt, size_t npackets) struct dma_test_frame *tf; dma_addr_t dma_addr; - tf = kzalloc(sizeof(*tf), GFP_KERNEL); + tf = kzalloc_obj(*tf); if (!tf) return -ENOMEM; diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c index 3ced37b4a869..317780b99992 100644 --- a/drivers/thunderbolt/domain.c +++ b/drivers/thunderbolt/domain.c @@ -126,7 +126,7 @@ static ssize_t boot_acl_show(struct device *dev, struct device_attribute *attr, ssize_t ret; int i; - uuids = kcalloc(tb->nboot_acl, sizeof(uuid_t), GFP_KERNEL); + uuids = kzalloc_objs(uuid_t, tb->nboot_acl); if (!uuids) return -ENOMEM; @@ -181,7 +181,7 @@ static ssize_t boot_acl_store(struct device *dev, struct device_attribute *attr, if (!str) return -ENOMEM; - acl = kcalloc(tb->nboot_acl, sizeof(uuid_t), GFP_KERNEL); + acl = kzalloc_objs(uuid_t, tb->nboot_acl); if (!acl) { ret = -ENOMEM; goto err_free_str; diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index d339ba835376..9d95bf3ab44c 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c @@ -427,7 +427,7 @@ static int icm_fr_get_route(struct tb *tb, u8 link, u8 depth, u64 *route) int ret, index; u8 i; - switches = kcalloc(npackets, sizeof(*switches), GFP_KERNEL); + switches = kzalloc_objs(*switches, npackets); if (!switches) return -ENOMEM; @@ -1769,7 +1769,7 @@ static void icm_handle_event(struct tb *tb, enum tb_cfg_pkg_type type, { struct icm_notification *n; - n = kmalloc(sizeof(*n), GFP_KERNEL); + n = kmalloc_obj(*n); if (!n) return; @@ -2246,7 +2246,7 @@ static int icm_usb4_switch_nvm_authenticate(struct tb *tb, u64 route) struct tb_cfg_request *req; int ret; - auth = kzalloc(sizeof(*auth), GFP_KERNEL); + auth = kzalloc_obj(*auth); if (!auth) return -ENOMEM; diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index 6d0c9d37c55d..2bb2e79ca3cb 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -587,7 +587,7 @@ static struct tb_ring *tb_ring_alloc(struct tb_nhi *nhi, u32 hop, int size, dev_dbg(&nhi->pdev->dev, "allocating %s ring %d of size %d\n", transmit ? "TX" : "RX", hop, size); - ring = kzalloc(sizeof(*ring), GFP_KERNEL); + ring = kzalloc_obj(*ring); if (!ring) return NULL; @@ -1020,7 +1020,7 @@ static bool nhi_wake_supported(struct pci_dev *pdev) * If power rails are sustainable for wakeup from S4 this * property is set by the BIOS. */ - if (device_property_read_u8(&pdev->dev, "WAKE_SUPPORTED", &val)) + if (!device_property_read_u8(&pdev->dev, "WAKE_SUPPORTED", &val)) return !!val; return true; diff --git a/drivers/thunderbolt/nvm.c b/drivers/thunderbolt/nvm.c index 6901058b7ac0..3dfa70ea6570 100644 --- a/drivers/thunderbolt/nvm.c +++ b/drivers/thunderbolt/nvm.c @@ -330,7 +330,7 @@ struct tb_nvm *tb_nvm_alloc(struct device *dev) return ERR_PTR(-EOPNOTSUPP); } - nvm = kzalloc(sizeof(*nvm), GFP_KERNEL); + nvm = kzalloc_obj(*nvm); if (!nvm) return ERR_PTR(-ENOMEM); diff --git a/drivers/thunderbolt/path.c b/drivers/thunderbolt/path.c index f9b11dadfbdd..8713ea0f47c1 100644 --- a/drivers/thunderbolt/path.c +++ b/drivers/thunderbolt/path.c @@ -150,22 +150,17 @@ struct tb_path *tb_path_discover(struct tb_port *src, int src_hopid, num_hops++; } - path = kzalloc(sizeof(*path), GFP_KERNEL); + path = kzalloc_flex(*path, hops, num_hops); if (!path) return NULL; + path->path_length = num_hops; + path->name = name; path->tb = src->sw->tb; - path->path_length = num_hops; path->activated = true; path->alloc_hopid = alloc_hopid; - path->hops = kcalloc(num_hops, sizeof(*path->hops), GFP_KERNEL); - if (!path->hops) { - kfree(path); - return NULL; - } - tb_dbg(path->tb, "discovering %s path starting from %llx:%u\n", path->name, tb_route(src->sw), src->port); @@ -245,10 +240,6 @@ struct tb_path *tb_path_alloc(struct tb *tb, struct tb_port *src, int src_hopid, size_t num_hops; int i, ret; - path = kzalloc(sizeof(*path), GFP_KERNEL); - if (!path) - return NULL; - first_port = last_port = NULL; i = 0; tb_for_each_port_on_path(src, dst, in_port) { @@ -259,20 +250,17 @@ struct tb_path *tb_path_alloc(struct tb *tb, struct tb_port *src, int src_hopid, } /* Check that src and dst are reachable */ - if (first_port != src || last_port != dst) { - kfree(path); + if (first_port != src || last_port != dst) return NULL; - } /* Each hop takes two ports */ num_hops = i / 2; - path->hops = kcalloc(num_hops, sizeof(*path->hops), GFP_KERNEL); - if (!path->hops) { - kfree(path); + path = kzalloc_flex(*path, hops, num_hops); + if (!path) return NULL; - } + path->path_length = num_hops; path->alloc_hopid = true; in_hopid = src_hopid; @@ -339,7 +327,6 @@ struct tb_path *tb_path_alloc(struct tb *tb, struct tb_port *src, int src_hopid, } path->tb = tb; - path->path_length = num_hops; path->name = name; return path; @@ -372,7 +359,6 @@ void tb_path_free(struct tb_path *path) } } - kfree(path->hops); kfree(path); } @@ -586,7 +572,7 @@ int tb_path_activate(struct tb_path *path) tb_dbg(path->tb, "%s path activation complete\n", path->name); return 0; err: - tb_WARN(path->tb, "%s path activation failed\n", path->name); + tb_warn(path->tb, "%s path activation failed: %d\n", path->name, res); return res; } diff --git a/drivers/thunderbolt/property.c b/drivers/thunderbolt/property.c index 31aa0516932a..50cbfc92fe65 100644 --- a/drivers/thunderbolt/property.c +++ b/drivers/thunderbolt/property.c @@ -81,7 +81,7 @@ tb_property_alloc(const char *key, enum tb_property_type type) { struct tb_property *property; - property = kzalloc(sizeof(*property), GFP_KERNEL); + property = kzalloc_obj(*property); if (!property) return NULL; @@ -166,7 +166,7 @@ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block, unsigned int content_offset; struct tb_property_dir *dir; - dir = kzalloc(sizeof(*dir), GFP_KERNEL); + dir = kzalloc_obj(*dir); if (!dir) return NULL; @@ -247,7 +247,7 @@ struct tb_property_dir *tb_property_create_dir(const uuid_t *uuid) { struct tb_property_dir *dir; - dir = kzalloc(sizeof(*dir), GFP_KERNEL); + dir = kzalloc_obj(*dir); if (!dir) return NULL; diff --git a/drivers/thunderbolt/quirks.c b/drivers/thunderbolt/quirks.c index e81de9c30eac..9f7914ac2f48 100644 --- a/drivers/thunderbolt/quirks.c +++ b/drivers/thunderbolt/quirks.c @@ -23,6 +23,9 @@ static void quirk_dp_credit_allocation(struct tb_switch *sw) static void quirk_clx_disable(struct tb_switch *sw) { + if (tb_switch_is_titan_ridge(sw) && sw->nvm && sw->nvm->major >= 0x65) + return; + sw->quirks |= QUIRK_NO_CLX; tb_sw_dbg(sw, "disabling CL states\n"); } @@ -61,6 +64,10 @@ static const struct tb_quirk tb_quirks[] = { /* Dell WD19TB supports self-authentication on unplug */ { 0x0000, 0x0000, 0x00d4, 0xb070, quirk_force_power_link }, { 0x0000, 0x0000, 0x00d4, 0xb071, quirk_force_power_link }, + + /* Intel Titan Ridge CLx is unstable on early firmware versions */ + { 0x8086, PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE, 0x0000, 0x0000, + quirk_clx_disable }, /* * Intel Goshen Ridge NVM 27 and before report wrong number of * DP buffers. diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c index 13d64dbd2bc5..b1e8d9d6454d 100644 --- a/drivers/thunderbolt/retimer.c +++ b/drivers/thunderbolt/retimer.c @@ -410,7 +410,7 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status, } - rt = kzalloc(sizeof(*rt), GFP_KERNEL); + rt = kzalloc_obj(*rt); if (!rt) return -ENOMEM; diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index b3948aad0b95..c2ad58b19e7b 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -7,6 +7,7 @@ */ #include <linux/delay.h> +#include <linux/hex.h> #include <linux/idr.h> #include <linux/module.h> #include <linux/nvmem-provider.h> @@ -68,7 +69,7 @@ static void nvm_set_auth_status(const struct tb_switch *sw, u32 status) st = __nvm_get_auth_status(sw); if (!st) { - st = kzalloc(sizeof(*st), GFP_KERNEL); + st = kzalloc_obj(*st); if (!st) goto unlock; @@ -346,7 +347,7 @@ static int nvm_write(void *priv, unsigned int offset, void *val, size_t bytes) return ret; } -static int tb_switch_nvm_add(struct tb_switch *sw) +static int tb_switch_nvm_init(struct tb_switch *sw) { struct tb_nvm *nvm; int ret; @@ -364,6 +365,26 @@ static int tb_switch_nvm_add(struct tb_switch *sw) if (ret) goto err_nvm; + sw->nvm = nvm; + return 0; + +err_nvm: + tb_sw_dbg(sw, "NVM upgrade disabled\n"); + sw->no_nvm_upgrade = true; + if (!IS_ERR(nvm)) + tb_nvm_free(nvm); + + return ret; +} + +static int tb_switch_nvm_add(struct tb_switch *sw) +{ + struct tb_nvm *nvm = sw->nvm; + int ret; + + if (!nvm) + return 0; + /* * If the switch is in safe-mode the only accessible portion of * the NVM is the non-active one where userspace is expected to @@ -382,14 +403,12 @@ static int tb_switch_nvm_add(struct tb_switch *sw) goto err_nvm; } - sw->nvm = nvm; return 0; err_nvm: tb_sw_dbg(sw, "NVM upgrade disabled\n"); sw->no_nvm_upgrade = true; - if (!IS_ERR(nvm)) - tb_nvm_free(nvm); + tb_nvm_free(nvm); return ret; } @@ -2474,7 +2493,7 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent, if (upstream_port < 0) return ERR_PTR(upstream_port); - sw = kzalloc(sizeof(*sw), GFP_KERNEL); + sw = kzalloc_obj(*sw); if (!sw) return ERR_PTR(-ENOMEM); @@ -2502,8 +2521,7 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent, } /* initialize ports */ - sw->ports = kcalloc(sw->config.max_port_number + 1, sizeof(*sw->ports), - GFP_KERNEL); + sw->ports = kzalloc_objs(*sw->ports, sw->config.max_port_number + 1); if (!sw->ports) { ret = -ENOMEM; goto err_free_sw_ports; @@ -2576,7 +2594,7 @@ tb_switch_alloc_safe_mode(struct tb *tb, struct device *parent, u64 route) { struct tb_switch *sw; - sw = kzalloc(sizeof(*sw), GFP_KERNEL); + sw = kzalloc_obj(*sw); if (!sw) return ERR_PTR(-ENOMEM); @@ -3311,6 +3329,10 @@ int tb_switch_add(struct tb_switch *sw) return ret; } + ret = tb_switch_nvm_init(sw); + if (ret) + return ret; + if (!sw->safe_mode) { tb_switch_credits_init(sw); diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 4f5f1dfc0fbf..c69c323e6952 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -94,7 +94,7 @@ static void tb_queue_hotplug(struct tb *tb, u64 route, u8 port, bool unplug) { struct tb_hotplug_event *ev; - ev = kmalloc(sizeof(*ev), GFP_KERNEL); + ev = kmalloc_obj(*ev); if (!ev) return; @@ -2862,7 +2862,7 @@ static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port, { struct tb_hotplug_event *ev; - ev = kmalloc(sizeof(*ev), GFP_KERNEL); + ev = kmalloc_obj(*ev); if (!ev) return; diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index e96474f17067..217c3114bec8 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -419,9 +419,9 @@ enum tb_path_port { * @activated: Is the path active * @clear_fc: Clear all flow control from the path config space entries * when deactivating this path - * @hops: Path hops * @path_length: How many hops the path uses * @alloc_hopid: Does this path consume port HopID + * @hops: Path hops * * A path consists of a number of hops (see &struct tb_path_hop). To * establish a PCIe tunnel two paths have to be created between the two @@ -440,9 +440,10 @@ struct tb_path { bool drop_packages; bool activated; bool clear_fc; - struct tb_path_hop *hops; int path_length; bool alloc_hopid; + + struct tb_path_hop hops[] __counted_by(path_length); }; /* HopIDs 0-7 are reserved by the Thunderbolt protocol */ diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 9fa95c595ecc..f38f7753b6e4 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -180,19 +180,14 @@ static struct tb_tunnel *tb_tunnel_alloc(struct tb *tb, size_t npaths, { struct tb_tunnel *tunnel; - tunnel = kzalloc(sizeof(*tunnel), GFP_KERNEL); + tunnel = kzalloc_flex(*tunnel, paths, npaths); if (!tunnel) return NULL; - tunnel->paths = kcalloc(npaths, sizeof(tunnel->paths[0]), GFP_KERNEL); - if (!tunnel->paths) { - kfree(tunnel); - return NULL; - } + tunnel->npaths = npaths; INIT_LIST_HEAD(&tunnel->list); tunnel->tb = tb; - tunnel->npaths = npaths; tunnel->type = type; kref_init(&tunnel->kref); @@ -219,7 +214,6 @@ static void tb_tunnel_destroy(struct kref *kref) tb_path_free(tunnel->paths[i]); } - kfree(tunnel->paths); kfree(tunnel); } diff --git a/drivers/thunderbolt/tunnel.h b/drivers/thunderbolt/tunnel.h index 2c44fc8a10bc..4878763a82b3 100644 --- a/drivers/thunderbolt/tunnel.h +++ b/drivers/thunderbolt/tunnel.h @@ -37,7 +37,6 @@ enum tb_tunnel_state { * @src_port: Source port of the tunnel * @dst_port: Destination port of the tunnel. For discovered incomplete * tunnels may be %NULL or null adapter port instead. - * @paths: All paths required by the tunnel * @npaths: Number of paths in @paths * @pre_activate: Optional tunnel specific initialization called before * activation. Can touch hardware. @@ -69,13 +68,13 @@ enum tb_tunnel_state { * @dprx_work: Worker that is scheduled to poll completion of DPRX capabilities read * @callback: Optional callback called when DP tunnel is fully activated * @callback_data: Optional data for @callback + * @paths: All paths required by the tunnel */ struct tb_tunnel { struct kref kref; struct tb *tb; struct tb_port *src_port; struct tb_port *dst_port; - struct tb_path **paths; size_t npaths; int (*pre_activate)(struct tb_tunnel *tunnel); int (*activate)(struct tb_tunnel *tunnel, bool activate); @@ -107,6 +106,8 @@ struct tb_tunnel { struct delayed_work dprx_work; void (*callback)(struct tb_tunnel *tunnel, void *data); void *callback_data; + + struct tb_path *paths[] __counted_by(npaths); }; struct tb_tunnel *tb_tunnel_discover_pci(struct tb *tb, struct tb_port *down, diff --git a/drivers/thunderbolt/usb4_port.c b/drivers/thunderbolt/usb4_port.c index b5e06237261b..c32d3516e780 100644 --- a/drivers/thunderbolt/usb4_port.c +++ b/drivers/thunderbolt/usb4_port.c @@ -305,7 +305,7 @@ struct usb4_port *usb4_port_device_add(struct tb_port *port) struct usb4_port *usb4; int ret; - usb4 = kzalloc(sizeof(*usb4), GFP_KERNEL); + usb4 = kzalloc_obj(*usb4); if (!usb4) return ERR_PTR(-ENOMEM); diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c index 63c7be818b2c..754808c43f00 100644 --- a/drivers/thunderbolt/xdomain.c +++ b/drivers/thunderbolt/xdomain.c @@ -858,7 +858,7 @@ tb_xdp_schedule_request(struct tb *tb, const struct tb_xdp_header *hdr, { struct xdomain_request_work *xw; - xw = kmalloc(sizeof(*xw), GFP_KERNEL); + xw = kmalloc_obj(*xw); if (!xw) return false; @@ -1094,7 +1094,7 @@ static void enumerate_services(struct tb_xdomain *xd) continue; } - svc = kzalloc(sizeof(*svc), GFP_KERNEL); + svc = kzalloc_obj(*svc); if (!svc) break; @@ -1974,7 +1974,7 @@ struct tb_xdomain *tb_xdomain_alloc(struct tb *tb, struct device *parent, down = tb_port_at(route, parent_sw); tb_port_unlock(down); - xd = kzalloc(sizeof(*xd), GFP_KERNEL); + xd = kzalloc_obj(*xd); if (!xd) return NULL; |
